FFT是一種DFT的高效算法,稱為快速傅立葉變換(fast Fourier transform)。傅立葉變換是時域--頻域變換分析中最基本的方法之一。可以將一個信號變換到頻域。有些信號在時域上很難看出什麼特徵,不利於分析,但是如果變換到頻域之後,就很容易看出信號的特徵了。這就是很多信號分析採用FFT變換的原因。FFT也可以將一個信號的頻譜提取出來,常應用於頻譜分析上。
2 -採樣定理採樣頻率必須是信號的最高頻率的兩倍及其以上,才能保證被採樣的信號不失真。
3- FFT的物理意義現假設我們需要對一個信號進行採樣然後做FFT分析,設定其採樣頻率為Fs,信號的頻率F,採樣點數為N。那麼FFT之後結果其實就是一個為N點的複數。每一個點就對應著一個頻率點。該點的模值,就是該頻率值下的幅度特性。
假設經過FFT之後得到的某點n,使用複數表示為a+bi,則該點的參數如下:
模值為A(n)
相位為P(n) = atan2(b, a)
頻率表達式為:Fn = (n - 1) * Fs / N
幅度(n ¹ 1) = A(n) / (N / 2)
幅度(n = 1) = A(n) / N (直流分量0Hz)
解析度 = Fs / N
例:
假設現在有一個信號由三個波形組成,分別是幅度為2的直流信號、幅度為3頻率為50Hz相位為-30度的正弦波、幅度為1.5頻率為75Hz相位為90度的正弦波。使用數學表達式表示為如下所示:
S=Adc+A1*cos(2*pi*F1*t+pi*P1/180)+A2*cos(2*pi*F2*t+pi*P2/180);
假設我們以256Hz採樣頻率對該信號進行採樣,採樣點數為256點,即N = 256。由上面總結的公式可是某點n對應的頻率為 Fn = (n - 1) * 256 / 256 = n-1,我們使用數學模型模擬的信號頻率分別為0Hz、50Hz、75Hz,由於採樣的點是從1開始的,因此對應FFT運算之後的數據應該是1點、51點、76點,只要分析以上三點的數據即可知道對應波形的幅度、相位等信息。
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點、51點、76點對應的模值分別為512、384、192,因此按照以上公式可以得出n=1時頻率為0Hz點對應的為直流分量,該點的幅度為:A(1) = 512 / N = 2,51點對應的幅度為:A(51)= 384 / (N / 2)= 3,76點對應的幅度為:A(76)= 192 / (N / 2)= 1.5。
相位計算:對於直流信號來說無相位可言,51點對應的相位為:atan(-192, 332.55) = -0.5236,計算的結果為弧度,轉換成角度為:180*(-0.5236)/ p = -30.0001度,76點對應的相位為:atan(192,3.4315E-12) = 1.5708,換算成角度為:90.0002,由此可見,分析後的數據和我們設定的數學模型是相符合的。Matlab仿真結果如下:
Matlab仿真代碼如下:
close all; %先關閉所有圖片
Adc=2; %直流分量幅度
A1=3; %頻率F1信號的幅度
A2=1.5; %頻率F2信號的幅度
F1=50; %信號1頻率(Hz)
F2=75; %信號2頻率(Hz)
Fs=256; %採樣頻率(Hz)
P1=-30; %信號1相位(度)
P2=90; %信號相位(度)
N=256; %採樣點數
t=[0:1/Fs:N/Fs]; %採樣時刻
%信號
S=Adc+A1*cos(2*pi*F1*t+pi*P1/180)+A2*cos(2*pi*F2*t+pi*P2/180);
%顯示原始信號
plot(S);
title('原始信號');
figure;
Y = fft(S,N); %做FFT變換
Ayy = (abs(Y)); %取模
plot(Ayy(1:N)); %顯示原始的FFT模值結果
title('FFT 模值');
figure;
Ayy=Ayy/(N/2); %換算成實際的幅度
Ayy(1)=Ayy(1)/2;
F=([1:N]-1)*Fs/N; %換算成實際的頻率值
plot(F(1:N/2),Ayy(1:N/2)); %顯示換算後的FFT模值結果
title('幅度-頻率曲線圖');
figure;
Pyy=[1:N/2];
for i=1:N/2
Pyy(i)=phase(Y(i)); %計算相位
Pyy(i)=Pyy(i)*180/pi; %換算為角度
end;
plot(F(1:N/2),Pyy(1:N/2)); %顯示相位圖
title('相位-頻率曲線圖');
本節將使用STM32官方提供的DSP庫運行FFT算法,使用DSP庫的好處在於FFT的運算時間很快,在72Mhz的主頻下運行256點的FFT僅僅只需要零點幾毫秒,能基本滿足我們的測試FFT的需求。
1. void Init_Single(void)
2. {
3. unsigned short i;
4. float fx;
5.
6. for(i = 0; i < N; i++)
7. {
8. fx = 1500 * sin(PI2 * i * 350.0 / Fs) +
9. 2700 * sin(PI2 * i * 8400.0 / Fs) +
10. 4000 * sin(PI2 * i * 18725.0 / Fs);
11. In_Array[i] = ((signed short)fx) << 16;
12. }
13.}
14.
15.void Get_Single_Message()
16.{
17. signed short lX,lY;
18. float X,Y,Mag;
19. unsigned short i;
20. unsigned int f = 0;
21.
22. SEGGER_RTT_printf(0, "Num f(Hz) A X Y\n");
23.
24. for(i = 0; i < N/2; i++)
25. {
26. lX = (Out_Array[i] << 16) >> 16;
27. lY = (Out_Array[i] >> 16);
28. X = N * ((float)lX) / 32768;
29. Y = N * ((float)lY) / 32768;
30. Mag = sqrt(X * X + Y * Y) / (N / 2); //某點的幅值=該點的模值/(N/2)
31. if(i == 0)
32. MagArray[i] = (unsigned long)(Mag * 32768);
33. else
34. {
35. MagArray[i] = (unsigned long)(Mag * 32768);
36. f += 175;
37. }
38.
39. SEGGER_RTT_printf(0, " %d %d %d %d %d\n", i, f, MagArray[i], Mag, Y);
40. }
41.
42. SEGGER_RTT_printf(0, "\n");
43.}
以上若有不嚴謹之處還請各位指出,謝謝!