算法:FFT的物理意义及C代码
| 分类: 信息技术研究 |
转:FFT结果的物理意义
S=2+3*cos(2*pi*50*t-pi*30/180)+1.5*cos(2*pi*75*t+pi*90/180)
我们来看看FFT的结果的模值如图所示。
1点: 512+0i
2点: -2.6195E-14 - 1.4162E-13i
3点: -2.8586E-14 - 1.1898E-13i
50点:-6.2076E-13 - 2.1713E-12i
51点:332.55 - 192i
52点:-1.6707E-12 - 1.5241E-12i
75点:-2.2199E-13 -1.0076E-12i
76点:3.4315E-12 + 192i
77点:-3.0263E-14 +7.5609E-13i
结果如下:
1点: 512
51点:384
76点:192
然后再来计算相位信息。直流信号没有相位可言,不用管它。先计算50Hz信号的相位,atan2(-192, 332.55)=-0.5236,结果是弧度,换算为角度就是180*(-0.5236)/pi=-30.0001。再计算75Hz信号的相位,atan2(192, 3.4315E-12)=1.5708弧度,换算成角度180*1.5708/pi=90.0002。可见,相位也是对的。
根据FFT结果以及上面的分析计算,我们就可以写出信号的表达式了,它就是我们开始提供的信号。
文件fft.c
#include
#include "fft.h"
float *SIN_TAB;//定义正弦表的存放空间
int FFT_N =
1024;//定义采样点大小
struct compx EE(struct compx a,struct compx b)
{
}
void create_sin_tab(float *sin_t,int PointNum)
{
}
float sin_tab(float pi)
{
}
float cos_tab(float pi)
{
}
void FFT(struct compx *xin)
{
}
fft.h
#ifndef FFT_H
#define FFT_H
#define PI
3.141592653589793238462643
struct compx {float
real,imag;};
extern void create_sin_tab(float *sin_t,int PointNum);
extern void FFT(struct compx *xin);
#endif // FFT_H
程序主要分为两个部分,第一部分主要采用雷德算法来实现倒位序,第二部分主要是利用已经生成好的旋转矩阵做蝶形变换。
举例:工程应用
为了找到基波位置,我们对第一次平均值做fft变换。第一次平均值即反映了ADC采样的值得整体趋势,只是在幅值上有所降低。ADC的定时器触发的采样频率为20KHz,40个采样点一次平均后的采样频率为500Hz,故fft的采样频率为500Hz(也即fft变换后最大频率不会达到500Hz)。
fft的采样点为1024点。故fft的分辨率约为0.49Hz。下面对具体程序和实际情况分析。
fft handle.c
void FFT_handle(u16 Input_voltage)
{
首先要求出fft变化后的各频率点的模值,i=0对应直流分量,其次找到最大频率点(即基波),但程序界定i<15,故滤除高于15*1.49=7.4Hz的分量。
在debug全速运行时,程序稳定状态下测得Max i=9,故对应4.4Hz。
用信号发生器测得被ADC采样波形和将其做fft变换。可以看出基波频率为4.148Hz,而示波器fft变换后最大模值点为4.19Hz。
由此得出结论:模拟测试4.14Hz与程序结果4.4Hz(i=9)基本一致,误差来源于fft采样分辨率0.49Hz。

加载中…