最近在做单片机实时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