本帖最后由 weizhongc 于 2015-4-28 01:28 编辑
前几天弄了个频谱显示,
本来真的想送给女友的,然后花了好几个晚上做出来了,
想想还是算了,好像没什么用。
我还是把M4上使用DSP 库 FFT 的经验分享一下吧,有问题的话,可以提问啊,哈哈 要是大虾的 看到我写得有问题也可以多多指点啊。别喷我啊
首先是基本知识的普及:
采样定理,就是大概是采样率要是声音频率的2倍,这样才能采样之后的数字信号完整地保留了原始信号中的信息,我也不知道为什么的,我也是复制的,懂可以补充下啊。
那接下来就是DSP库 的FFT使用问题了,其实很简单的。就下面四个行啊。
arm_cfft_radix4_instance_f32 S;
arm_cfft_radix4_init_f32(&S, _fftSize, ifftFlag, doBitReverse);
arm_cfft_radix4_f32(&S, _inputBuffer);
arm_cmplx_mag_f32(_inputBuffer, _outputBuffer,fftSize);
蓝色字是函数详解,可以忽略,我们要会用就行了。
第一个函数arm_cfft_radix4_init_f32,用于初始化FFT运算相关参数,其中:fftLen用于指定FFT长度(16/64/256/1024/4096)我的例程是256;ifftFlag用于指定是傅里叶变换(0)还是反傅里叶变换(1),本章设置为0;bitReverseFlag用于设置是否按位取反,本章设置为1;最后,所有这些参数存储在一个arm_cfft_radix4_instance_f32结构体指针S里面。
第二个函数arm_cfft_radix4_f32就是执行基4浮点FFT运算的,pSrc传入采集到的输入信号数据(实部+虚部形式),同时FFT变换后的数据,也按顺序存放在pSrc里面,pSrc必须大于等于2倍fftLen长度。另外,S结构体指针参数是先由arm_cfft_radix4_init_f32函数设置好,然后传入该函数的。
第三个函数arm_cmplx_mag_f32用于计算复数模值,可以对FFT变换后的结果数据,执行取模操作。pSrc为复数输入数组(大小为2*numSamples)指针,指向FFT变换后的结果;pDst为输出数组(大小为numSamples)指针,存储取模后的值;numSamples就是总共有多少个数据需要取模。(复制于正点原子论坛)
知道这几个函数,那到底在程序里面怎么使用这才是问题,刚刚上面说的采用定律在这里就会用到了。如果我们要用FFT分辨的频率达到8K,
那么我们的采样率就要16K 或者以上了(其实16K是最好了吧)。以此类推,你如果想做0~1kHz 范围 那么你的采样率就是要2x1K=2Khz。其实说到底就是分析的频率范围是采样率的1/2,不然就是采样率是分析频率的两倍啊。
行了,那现在要用多大的采样率就由你的分析频率来确定了。在本例中我想做的是0到20K的FFT,可是我又不知道怎么去修改LPC54102 ADC的采样率,所以我在adc的中断里搞了个LED翻转。哈哈,我示波器量到了20Khz,那我就做 10Khz的FFT(10=20khz/2),我就是这样采样率来决定分析的频率啊。然后直接把电位器调到中间作为抬升电压。然后搞个电容耦合进去就搞定了。靠。我太聪明了懒到不想去知道adc怎么配置,方便快捷啊。
上面讲的就是分析的频率范围,采样率,那么分辨率呢,这个就更简单了,就是分析的频率/256(我做256FFT),那么就是10000HZ/256 ;
还有可能会遇到的问题就是 M4在做FFT时, 数组_inputBuffer 要保证 偶数个体是实部 (我们采用的数据值) 奇数 个体是虚部 (填0就好了)
所以我们分析值放入 _inputBuffer 要注意 例如 float32_t testInput_f32_10khz[2048] = { -0.865129623056441, 0.000000000000000, -2.655020678073846, 0.000000000000000, 0.600664612949661, 0.000000000000000, 0.080378093886515, 0.000000000000000, -2.899160484012034, 0.000000000000000, 2.563004262857762, 0.000000000000000,}
还有个要注意的是 _inputBuffer 在计算的时候数据会给填充,所以最好开辟多一个数组来做缓存。
现在我讲解我的FFT处理了。 就是ADC采用到256个数据后,做256FFT处理,然后把计算出来的模值显示在TFT上就好了。
总结:其实整个过程 不一定要你对每次采集到的256个数据进行计算的。 我们1s 取某几组256个ADC值就行了,这几组就是我们的帧数了。FFT出现结果很奇怪是,看看数组间复制过程是否出现问题。
FFT显示效果