基于ARM-DSP库在STM32中实现FFT
摘要
关键词
DSP,FFT,STM32,MATLAB
正文
1.引言
DSP有两层意思,一层是指数字信号处理技术(Digtal Signal Processing),另外一层指数字信号处理器(Digtal Signal Processor)。平时所说的DSP指的是第一层的意思,主要研究的是如何对信号进行采集、分析、变换、综合、估计与识别等,几乎在所有的工程技术领域都会涉及到信号处理问题,其信号主要表现形式有点、磁、光、机械、热、声等等。而第二层主要研究如何将理论上的数字信号处理技术应用与数字信号处理器中,专用的DSP芯片能够轻松的对数字信号进行变换、滤波等处理,还可实现更加复杂的运算,达到需要的目的。
传统的DSP芯片采用哈佛结构,而单片机采用的是冯•诺依曼结构,因此在运算能力上单片机肯定不如DSP专用芯片。但是随着近几年单片机的技术发展,性能越来越强,运算速度、运算精度等都有很大的提高。特别是目前以STM32系列单片机为主,发展势头强劲,内部除了集成常见的外设模块外,还有专用的DSP模块以及FPU(浮点运算)模块,官方同时有配套的DSP库可以直接使用,甚至跟着AI、大数据、边缘计算等兴起,都有配套的库或者方案可参考。而单片机相对DSP芯片有个最大的优势就是便宜,这对于低成本方案实现成为可能。
2.FFT相关函数介绍
DSP库可以源码和库两种方式移植,本文采用第一种。源码可以去keil官方网站获取,也可以通过安装好的MDK路径获得,位于MDK的安装路径下Arm\Packs\ARM\CMSIS\5.8.0\CMSIS\DSP。MDK版本要求5.25以上,编译器AC6.0以上。把其源码和头文件全部复制到MDK工程内,由于DSP库功能较多,可以根据自己的需求添加相应的头文件与源文件。
用单精度浮点实数arm_rfft_fast_f32函数实现快速傅里叶变换,主要涉及三个函数:
arm_rfft_fast_init_f32(arm_rfft_fast_instance_f32 *S, uint16_t fftLen):对FFT进行初始化处理,第一个参数是将封装好的FFT例化,定义傅里叶变换模型;第二个参数指定FFT的长度,支持32,64,128,256,512,1024,2048,4096点FFT。
arm_rfft_fast_f32(const arm_rfft_fast_instance_f32 * S, float32_t * p, float32_t * pOut, uint8_t ifftFlag):实现单精度浮点实数FFT的核心函数,第一个参数同样是对封装好的浮点FFT进行例化,但需要先调用arm_rfft_fast_init_f32初始化函数;第二个参数是FFT的实数缓冲区地址,比如要做1024点FFT,那么至少要保证有1024个缓冲区;第三个参数是FFT转换结果的地址,转换结果不是实数了,而是复数,按照实部-虚拟-实部-虚部,依次排列。比如做1024点FFT,这里的输出也会有1024个数据;第四个参数是设置FFT的变换类型,ifftFlag=0表示进行正变换,ifftFlag=1表示进行反变换。
arm_cmplx_mag_f32(const float32_t * pSrc, float32_t * pDst, uint32_t numSamples):用于对单精度浮点实数FFT变换后的值进行求模处理,方便在二维平面做出频谱图。第一个参数是完成FFT变换后数据地址;第二个参数是FFT变换结果取模后的数据地址,第三个参数是需要取模的复数个数。
3.实验与仿真
首先,在STM32和MATLAB中生成相同的时域信号,然后再各自对该信号做1024点FFT变换,双方生成的时域信号如下:
,
采样频率为,STM32完成FFT后,通过串口把数据传至PC端进行画图。最终STM32与MATLAB各自完成FFT前后的时域图、频域图以及绝对误差图如图1所示。
图1. STM32与MATLAB做FFT的结果
由图1.a可以看出,二者生成的时域信号基本一致,图1.c也正好说明了这一点,二者误差非常小,对于信号本身来说几乎可以忽略不计;由图1.b可以看出,不论是STM32还是MATLAB都对原信号做出了正确的FFT,清楚地看到四个频率分布,位置准确。而且二者幅度误差也很小,图1.d也正好说明这一点。
4.总结
文章先是介绍了STM32与传统的DSP芯片在做信号处理的不同之处,接着重点描述了ARM-DSP库移植,以及做FFT变换的方法。最后通过实验对比STM32和MATLAB做FFT运算的结果,发现二者误差非常小。说明STM32可以在较低端的行业完成DSP功能,可以替代传统的DSP芯片,有一定的应用前景。
...