你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32的FFT运算示例及应用提醒  

[复制链接]
fightingboon 发布时间:2019-10-31 13:33
这里将使用ST公司的STM32F411discovery开发板,就如何实现浮点FFT运算做个简单应用示例,并给些应用提醒。下面用到的IDE是ARM MDK。
因为要用到ARM公司提供的DSP库,所以需先开启一些必要的宏开关并添加相关库文件。STM32F4芯片支持DSP指令且自带浮点运算单元即FPU。
在MDK集成开发环境的相关配置栏添加__CC_ARM,__TARGET_FPU_VFP,ARM_MATH_CM4,并启用了硬件FPU。

5 b! S" i4 f: F& @+ z+ G3 m# r
11.png

/ L) p. ~% g9 V- @* M3 b. }
添加ARM提供的DSP库文件。如果使用STM32Cube库的话,该库文件一般在这个目录下【以STM32F4cube库为例】,有4个库文件。
) o$ l5 J! t' \4 E, w9 v" Q+ c
22.png
( D4 M0 }, Z: t9 ^+ R) J) t! O
其中cortexM4b是基于大端存储模式但不支持硬件FPU时所用的DSP库文件,cortexM4l是基于小端存储模式但不支持硬件FPU时所用的DSP库文件。而cortexM4bf是基于大端存储模式且支持硬件FPU的芯片所用到的库文件,显然,cortexM4lf是基于小端模式且支持硬件FPU的芯片所用到的库文件。
这里我们添加arm_cortexM4lf_math.lib即可,STM32芯片采用小端存储模式,且STM32F4内置FPU硬件单元。
这里提醒下,首先,DSP库不要选择错了。其次,在添加.lib库文件时,添加时注意选择文件类型为lib。如果以别的文件类型强行添加进去后,编译可能提示出错。有时一会半会还找不到出错原因。

1 r6 u) N$ r! U
33.png

; |$ t$ W' h0 ?; W% W
另外,我们还需在用户代码里添加包含文件:#include"arm_math.h"。至于其它头文件按需添加即可,比方math.h头文件。
下面开始看看具体的代码实现。
先做基本变量的准备及定义,比如用于FFT运算的点数,用于FFT运算的输入数据数组,输出数据数组、存放各频点初始相位的数据数组等。
* |6 `! e3 A) m# r0 |8 ]
44.png

& t4 Y3 K- l2 W; ^, s, L
这里使用几个正、余弦信号函数叠加产生一组信号序列。其中,有一个幅度为3的直流分量。另外几个分别是频率为200Hz、400Hz、600Hz、800Hz、1000H,幅度值分别是1、2、4、8、16的正、余弦信号函数。各输入数据项的虚部均设置为0。

$ ^0 o7 W! O& c( M2 x  M0 _6 }& [
55.png

/ q4 i# o! {! L( l
这里假设采样频率Fs=5120Hz,期望的最小频率分辨率为20Hz,则最小采样点数不要少于5120/20,即这里选择256点。【如果希望频率分辨率更高,可以加多采样点数】。

6 @0 t' a1 c8 |8 F) E: i  b, P
其中,采样频率不得低于最高被采样信号频率的2倍。关于这个采样频率及采样点数的选择给几点提醒供参考:
1、采样点数它往往有个最小值需求,由采样频率和所期望的最小频率分辨率决定。
2、整体上讲,增加采样点数有利于提高频率分辨率或改善运算结果。不过,增大样点数时既要考虑它对计算速度影响,同时还得考虑对微处理器内存的开销。比方128点和1024点的内存开销差别就较大了。
3、在选择采样点数时,除了考虑满足最小值要求外,还得结合具体选用的FFT相关函数类型,比方说是基4还是基2的。如果使用基4的FFT运算函数,则样点数须满足4的整数幂。如果使用基2的FFT运算函数,则样点数须满足2的整数幂。
4、具体到使用ARM的DSP库函数进行FFT运算时,还得遵循函数本身所支持的样点数约定,并不是你想多少就多少。比如,以下面函数为例:
% K+ c1 W4 B, c5 ^
66.png

8 [: _5 l8 c$ C* `/ r" j+ v- N
基于上面FFT函数,如果你使用128点、512点、甚至高于1024点都不支持,或者说计算结果误差很大。【当你点数选择不当时,编译时目前是没有任何提示的。】
5、有些场合为了满足FFT运算要求,计算所需样点数可能多于实际数据量,这时我们在数据序列尾部补零凑齐。比方经过评估希望512点,结果实际数据才500个点,我们可以考虑补零以便于计算。这样做可以减小栅栏效应,但不会提高实际频率分辨率。
6、采样频率要满足不低于最高被采样信号频率的2倍的要求,但并非单纯的越高越好。一般取其3~6倍,具体应用时合理选择。
关于采样点数的拟定就提醒这些,尤其上面的第3点、第4点,在使用相关函数时,最好看看函数原型说明。【注:我们在PC端使用诸如Matlab、Octave等数学工具时样点数往往可以做到比较随意、自由。】
好,基本数据准备工作做完了,下面就是调用几个函数来完成FFT运算工作。

. `- U1 a& ^0 j5 f* v
77.png

1 a  ?7 ~# Y$ \' r5 U7 s, i
运行相关代码后,我们可以看到不同频点所对应的模值。
对于直流信号,其对应的频点位为0,计算出来的模值是其实际幅度的N倍,【N即FFT运算用到的样点数,这里就是256】,其它非直流频点的模值经FFT计算后的结果为实际幅度值的N/2倍。
我们可以先使用Matlab或Octave模拟一下输出结果。下面是用Octave模拟出来的结果。
9 v! p* c( ?  B1 j/ ]0 S8 @# s$ z
88.png

/ ?2 Y8 Z( T$ Q% F2 K4 O& F( o  J
因为经过FFT运算后的输出结果由对称的两部分组成,我们只需查看前面半部分即可。
如下图所示:

5 ^* ]2 S" i  C5 J% @- }
99.png
0 U1 ?! `; X# h" i
因为采样频率是5120,采样点数为256,即每两个采样点的频率间隔为20Hz.我们不难从上图看出直流分量0Hz以及200Hz、400Hz、600Hz、800Hz、1000Hz几个频点信号的位置及模值。图中0点位处所对应的模值就是直流分量的模值。因为各点位的频率间隔为20Hz,所以图中点位50处所对应的模值就是原信号中1000Hz余弦信号的模值。【前面提过了,FFT计算所得模值跟各频点信号实际幅度值还有个对应关系】
我们再来看看经过STM32F4芯片进行FFT运算后的实际结果。计算后各频点的模值存放在数组fft_output[256]里,我们可以进行查看、比较。不难理解,如果点数越多,数组数据量也就越多,看起来并不太直观方便。我这里将FFT输出结果按照频点顺序在调试界面周期性地显示出来,如下图所示。其中,红色波形是信号频谱及模值,绿色斜线是频点递增变化曲线。
! S: P+ I. I' u
10.png
: p- k' C. P. A9 C% _) Y- K
同样,我们只需查看FFT完整输出的前半部分结果。

* m8 ]8 p1 f6 [
111.png

- T, T* Z) m( u' x
这里的零点处所对应的模值就是直流分量的模值,理论值应该为3*N,即3*256=768,实际计算结果也是768;其它5根线分别对应200Hz、400Hz、600Hz、800Hz、1000Hz这几个频点信号的模值。在显示界面轻点鼠标即可看到各处的频点位置及对应的模值。
当然,我们也可以到经FFT运算后的输出数组里去查看数据,相比之下,只是没有这么直观快捷。【下图是部分数据截图】
; {: L! q! g0 N. J
222.png
" P6 `, s- Z* e4 l7 ]' f& X5 D
另外,我们还可以看看各个频点信号的初始相位值。同样,我们也可以先用Octave模拟运算结果。基于数学工具的运算结果如下:

9 U% \4 _6 Q/ Q
333.png

$ V8 Z! n. n* l4 V  c$ h
我们再看看基于STM32F4芯片的FFT计算结果:
7 ]& j. m/ Q# q+ Y; U) Z
444.png
$ V% ~' v, i: B% |# |  L- u% S, R
这里提醒下,初始相位的计算结果是按照余弦函数计算的,所以如果使用正弦函数产生的信号的话,就涉及到一个三角函数的转换关系sinx=cos(pi/2-x),经过转换后所得的余弦函数的初始相位值跟计算结果就一致了。
整体上,基于上面的参数所得FFT计算结果,跟理论值还是非常一致的。不过,要提醒的是,即使对于同一个被采样信号,因选取了不同的采样频率和采样点数做频谱分析时,可能会出现不同程度的误差。所以,为了减小误差,我们要选择合适的采样频率与采样点数,更多细节可以查看相关资料。
* U( v& e( l5 Z

3 S7 b* J3 o8 g# z
6 T) ^) w! u7 H  j

评分

参与人数 2 ST金币 +14 收起 理由
wolfgang2015 + 6 赞一个!
子曰好人 + 8 赞一个!

查看全部评分

收藏 8 评论18 发布时间:2019-10-31 13:33

举报

18个回答
gieg 回答时间:2020-5-3 15:14:41
请问有谁知道对于同一个信号,怎样选取了采样频率和采样点数做频谱分析,为什么我采用STM32F4对幅值为0-3.3V,频率为10KHz,占空比为50%的方波进行采集,采样率为300KHz,使用DMA采集256个点,进行fft运算,输出幅值与理论值有百分之十的误差
gieg 回答时间:2020-5-3 15:14:17
请问有谁知道对于同一个信号,怎样选取了采样频率和采样点数做频谱分析,为什么我采用STM32F4对幅值为0-3.3V,频率为10KHz,占空比为50%的方波进行采集,采样率为300KHz,使用DMA采集256个点,进行fft运算,输出幅值与理论值有百分之十的误差
gieg 回答时间:2020-5-3 15:13:50
请问有谁知道对于同一个信号,怎样选取了采样频率和采样点数做频谱分析,为什么我采用STM32F4对幅值为0-3.3V,频率为10KHz,占空比为50%的方波进行采集,采样率为300KHz,使用DMA采集256个点,进行fft运算,输出幅值与理论值有百分之十的误差
AI++ 回答时间:2019-10-31 23:07:10
学习了
子曰好人 回答时间:2019-11-1 08:49:22
谢谢分享,点个赞
网络孤客 回答时间:2019-11-2 15:56:45
谢谢分享!
Kevin_G 回答时间:2019-11-5 11:52:11
厉害
qiangtech 回答时间:2019-11-5 14:27:29
厉害了,学习。
wolfgang 回答时间:2019-11-6 01:40:46
讲得透彻
七七baba 回答时间:2019-11-8 15:33:16
学习一下
ychlucky 回答时间:2019-11-11 00:00:18
fkxy 回答时间:2019-11-11 11:08:38
学习了
Love_ST 回答时间:2019-11-16 08:23:51
学习了
cos12a-21701 回答时间:2019-11-20 12:24:35
很好。谢谢了。
仰望星期五 回答时间:2020-4-27 15:30:38
最近在学习单片机的FFT,这篇文章提供了一点思路,,多谢多谢。
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版