最近在做單片機實時fft-ifft分析,遇到了許多問題,由於傳感器對於外部環境敏感,表現不穩定,沒有硬件濾波,導致必須做軟件濾波後方可進行後續分析,查閱了很久的fft資料,一併發上來,給大家參考。
單片機要求代碼量少,且使用的內存小,故挑選的代碼很有針對性。
1:c語言版本fft-ifft代碼
1.1 https://blog.csdn.net/weixin_42882232/article/details/81414642此代碼由於缺少必要註釋,導致輸出參數混淆,簡單sin函數測試,同matlab對比,無法得出正確數據,沒明白fft原理,無法自己修改,也不知道到底代碼對不對。
1.2 https://download.csdn.net/download/zhaopeizhaopeipei/12266546此代碼運算速度很快,內存佔用也很小,唯一缺點就是代碼量太大,只能屏蔽沒有調用過的,即便如此也佔用了很大的單片機內存,需要嘗試後在做決定。需要提前看.c的註釋說明,有複數及實數fft調用,matlab測試過複數調用,64,18,256,512點均沒有問題。
int len=64;
int nCurIndex = 0;
i=0;
for (int nBlock=0; nBlock<nSize-len; nBlock+=len)//nSize爲數據長度pHong爲數據的實部及虛部,順序存儲,虛部爲0
{
nCurIndex = nBlock;
cdft(len*2, -1, pHong+nCurIndex*2);//輸入實部,虛部,實部,虛部交替存儲......,輸出爲實部,虛部,實部,虛部交替存儲
}
for (nBlock=0; nBlock<nSize-len; nBlock+=len)
{
nCurIndex = nBlock;
for (int m=0; m<len-1;m++)
{
k=1.0*m/(nPow2Len*dt);
if( ( (k) >= ff1 && (k) <= ff2) || (k) >= (1/dt-ff2) && (k <= (1/dt - ff1) ) )
{
//data[m] = data[m];
}
else
{
pHong[nCurIndex*2 + 2*m] = 0;
pHong[nCurIndex*2 + 2*m+1] = 0;
}
}
// pHong[nCurIndex*2] = 0;
// pHong[nCurIndex*2] = 0;
}
//頻域抽取完成後,ifft逆變換
for (nBlock=0; nBlock<nSize-len; nBlock+=len)
{
nCurIndex = nBlock;
cdft(len*2, 1, pHong+nCurIndex*2);//反變換 輸出數據爲實部虛部,實部虛部交替存儲
for (int i=0;i<len*2;i++)
{
pHong[i]=pHong[i]/(len*2);//實部爲ifft變換後的數據
}
}
% f1=0;%帶通
% f2=8;
% %%處理data1
% Nout = 128;
% N=128;
% NFFT = 2^nextpow2(N); % Next power of 2 from length of y
% y=k;
% f = (0:length(y)-1)*Fs/length(y);
% yy=zeros(1,length(y));
% for m=0:Nout-1
% if(m/(N*dt) > f1 & m/(N*dt) < f2) | (m/(N*dt) > (1/dt-f2) & m/(N*dt) < (1/dt -f1))
% yy(m+1)=y(m+1);
% else
% if m<N-1
% yy(m+1)=0;
% end
% end
% end
% yy(1)=y(1);
% yy(Nout)=y(Nout);
% hong1=real(ifft(yy));
1.3 arm dsp庫實現fft 代碼需要檢查版本,據說是版本1.4一下的實數fft有錯誤,無法使用,dsp文檔中部分實數fft的輸出參數同文檔描述不一致,需要注意下。此庫實現fft代碼量編譯後令人驚異的小,調用時也需要明白調用函數參數的使用方法,不能隨意調用,以防止由於誤用引入錯誤。
https://wenku.baidu.com/view/69308ac43c1ec5da50e270c8.html?sxts=1585013642187
https://wenku.baidu.com/view/81b29abd0066f5335a8121f9.html
https://wenku.baidu.com/view/f9d54f486f1aff00bfd51e5f.html?sxts=1585013667786
https://wenku.baidu.com/view/9cbc1a94eff9aef8951e061b.html?rec_flag=default&sxts=1585013684303
2:實時fft關於頻譜泄漏的問題
https://blog.csdn.net/wordwarwordwar/article/details/72590859
https://blog.csdn.net/wordwarwordwar/article/details/72590680
https://blog.csdn.net/kenjianqi1647/article/details/79589782文章寫得很明白,如果有可能截取週期性的信號,那就截取週期性信號,如果不可以,可以考慮增加窗函數的使用。
添加窗函數參考https://www.cnblogs.com/VerilogHDL/p/5959548.html