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

【经验分享】STM32F7 DSP库 FFT过程记录

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下
8 Q, a0 H- \% x5 r& u/ o, f3 KSTM32F767IGT60 F( C8 M7 k. K6 }0 [6 D
Keil5.219 z! x) i7 n) }. t
Cube MX4.24% {% Y7 B) ~# g7 F0 `1 I
arm_cortexM7lfdp_math.lib
8 \3 W0 }8 P; ~: X- c正点原子阿波罗开发板
$ ^. u2 L4 M: i" t+ L" Z* s" ^% s! z1 z& g5 t
准备DSP库
: O+ }3 n. c) @7 u0 L+ ^打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,
2 ~3 i1 f. B5 i! Z+ D/ V  N- c3 d7 c
20180311111030987.png
" B) e* }/ w4 {  X$ q3 u

/ g( l" C* w% S& @& a+ QDrivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。
: }, U! h. s0 A- ^+ p; v' r8 i# `Examples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):% A0 a1 K: {& {  I5 O

' e% v/ m9 N' p, E1 Z
20180311111810371.png

) a3 k  N! t) g
" g: s- _' ]+ v- d: TSource 中的文件如下(这些是 DSP库的源文件):6 r! S4 F  |5 R, M3 v# R, [3 M5 Y
& |  G4 R% X2 p. p' X" L
20180311111958592.png
9 K1 q" S4 S  `

: w- y1 `' m2 e源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。
, Q, [/ n& J" h8 P! Y' [# g0 L5 |9 g2 e
20180311112424199.png
0 R7 u$ a4 {, P2 y
! Z& n0 F! ^# \" G% W* {! g
库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。% O: l0 n" C6 e7 P. S+ M
$ _" h( ?, L( r
2018031111274971.png

- T4 I' A, |. {! x2 C! o# M' W0 b3 y5 O) V5 L' U  I# b/ K. n
确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。
. _8 t) Y! L7 n% @/ m) b
8 l6 l! P4 S0 n; m' q4 X+ [
20180311113253946.png

- e/ c# l$ T9 w2 ?" L3 x6 P+ d0 U6 s8 s/ y
下图为DSP库已添加到工程中。
6 }. W# @; Y2 e# I; [: \" T9 Y5 n
# N/ Q2 l4 E  `- ?. m% c
20180311113319114.png
; C& n3 A9 n  y3 v8 X9 q, I" r

1 O% }  m1 |% s+ H3 Z8 ]( A# h, w库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。  i1 `6 Z6 B* c2 x
: N  N7 u8 b5 n% |
20180311113402949.png

1 L: b7 ?) k8 D5 P: ^
( w1 q% u! U5 k; ^3 B: g函数说明+ @% ^5 D7 m1 J3 `, r' f
我用到的是实数FFT,即rfft。相关函数参见官方说明。& l6 j5 T# N. I' b
函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。
3 L% x5 d; \* ~0 `# Parm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。8 D) }: U2 G5 P
& Q0 ?! [2 S, W
2018031111470032.png

* h* Z3 I, f. e# i* ]( S5 B9 ]/ Y5 Z3 Z6 `
S是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。/ _7 K' m1 S) U8 C) R
另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。- U# {2 Z1 }+ F# P& r) \0 ~
' D6 \/ V" ^( J6 G
2018031111510511.png
; e7 g# q9 H6 ?* b  S5 @
! e$ n( n* _8 G' }# X
官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”
  n4 m/ \, d% y; W6 {1 R. w除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。
2 o3 V9 ?4 W7 q" E' m& w1 b/ U
) p( q+ d$ q& d' i! g6 t
20180311115611796.png

- t6 \$ o8 A5 ]7 j5 e) T
5 @0 ~+ _# a( ^6 d! |) N- @' B另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。
% t! d2 \% |, L/ B" T9 h1 E
& ?* d4 B! g! j8 e8 o# L. k: S# v  C
20180311115858812.png

9 A9 D! c0 ]/ [" o: @
% T5 B6 K: c, I& m( c! e代码示例% t( \, U6 s: o( u  C4 v
  1. include "DSP.h"7 o3 ]( ^1 t( _0 P
  2. include "arm_math.h"# Q+ h8 X5 z9 C
  3. define NPT  1024  //1024点FFT$ e; j, t" a- c, T: g/ \1 a
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz
    # ~/ \1 D/ g! K
  5. define PI2 6.28318530717959+ y( _$ d) x% x2 Y
  6. float32_t  testInput_f32[NPT];) b& m: h' B. Z5 J$ G
  7. float32_t  testOutput_f32[NPT];( O0 c" Q) k7 {  J5 m
  8. float32_t  testOutput[NPT];
    ; j5 M& ~- W: c7 |
  9. ' o' T3 g7 D; V3 B( v
  10. /*
    - |$ k# ]+ a, X2 g) q; i/ T
  11. ********************************************************************************************************* 7 R2 Z' C3 F. X$ F0 C0 @% {* \0 c* U7 _
  12. *  函 数 名: arm_rfft_fast_f32_app
    ' ]* U' d- g0 F6 E
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比 5 B$ F8 O! I; Y6 K: n5 M! c
  14. *  形    参:无
    ' N! V( `3 `/ x% h8 H$ |7 H4 z
  15. *  返 回 值: 无 1 w! X* m7 G/ ]& T7 u/ I
  16. ********************************************************************************************************* ' T/ u. u1 U5 d. {8 ]8 \$ o2 x3 e
  17. */
    ! h0 w1 v& h% B1 Q' d' r
  18. void arm_rfft_fast_f32_app(void)
    # |- f! k5 a! `" X& f; b
  19. { 1 H0 B! ]" b9 b) x, K5 f) p# [$ q
  20.   uint16_t i;   N1 H  T4 g, m
  21.   arm_rfft_fast_instance_f32 S;
    2 J2 g# k+ q9 x( y$ r8 B
  22. 6 ^$ k2 ]# J) `6 S3 n" g
  23.   /* 实数序列FFT长度 */ ) [0 b6 F3 l9 U9 ?
  24.   uint16_t fftSize = NPT;  
    $ i$ X" y" w1 E) h. L* O  ?8 S% c
  25.   /* 正变换 */
    " ?# ]# T: s9 n$ m, c4 {
  26.     uint8_t ifftFlag = 0;  ' K) E( U1 {& i1 m. F; B

  27. ; K4 u# V$ B/ \: Z6 D7 c- w
  28.   /* 初始化结构体S中的参数 */ 7 O# B' Z" I% a0 e! d4 B
  29.    arm_rfft_fast_init_f32(&S, fftSize);
    " m3 Q" [: E% i' j$ ^  Q

  30. 8 I6 K  j) y+ ^) S3 H. _: Y4 V
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */ : F* \; [( _9 @5 l9 u2 V. _7 W
  32.   for(i=0; i<1024; i++)
    6 ~- P( J& O- C/ U
  33.   {
    ; y7 b+ B& x2 c5 h
  34.     /*3种频率 50Hz 2500Hz 2550Hz */
    1 l5 |1 H) `* C# J: n4 g. R, Z
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) + 9 r2 n- t) Z2 K/ l/ i4 `
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  +
    4 N1 @+ ~7 D6 S
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs);
    + T/ D  Q* D0 ^; d
  38.   }
    ' v( _! B% s# {$ |- a. U

  39. ; I+ Z8 S! r/ K# d' f
  40.   /* 1024点实序列快速FFT */  
    5 E9 J- ~# a9 E5 B
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);
    ! _5 O; _$ v+ i2 f: U5 }

  42. 4 O4 E9 h1 K  W# M5 D: B& ]
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32
    ; Z/ t, p* e6 M
  44.      只求解出了512组   0 ?4 ^% Y. }% K( ~3 |
  45.   */  ( p( A& ]" C# }' H) }: _1 c
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize);
    / i/ x. o1 y4 d7 s* ~

  47. / s8 F8 c" w' t. P. G5 l
  48.   /* 串口打印求解的模值 */
    0 n' O. q0 l: F: I  m
  49.   for(i=0; i<fftSize/2; i++) 0 x( ?# S2 U3 t9 }; B- D" A- w
  50.   { ' F0 u  v5 {8 [. e# C
  51.     printf("%f\r\n", testOutput); + y' K( o9 f% ]* N8 I
  52.   }
    9 f& R3 Z' V1 Z: d: P
  53. }
复制代码
4 t+ S0 N; x, Z) I9 ^4 y
结果) W" y& Q. S2 `" a9 ~) P6 O
在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。8 `; O% F  F2 u6 S* l" u& i- V
) f9 S9 e% S. O+ u
20180311120547219.png
! S& I& H! @# Z/ Y

9 M3 b, q7 j3 J  U8 Z$ q$ f& ~$ A
20180311120659401.png

7 B# w' P; W0 @* o
  e' P  K: n) {6 ~4 S- n
20180311120749658.png

0 U9 v; G1 F! C, t7 W7 _4 e9 [2 [4 L$ i& k* B! X6 V

. W; z" S% O, N& k) q3 P对数据plot画图,结果如下" L& A* a# A) z' m' i* x
4 l! h2 o3 ^# W2 N  g2 D5 s
20180311120824877.png

% X" V# V1 |- f+ O7 e5 D) m; R
' ?6 O2 o+ o/ k可以看出,FFT之后分析出包含信号的频率为50Hz,2500Hz,2550Hz,与生成信号 testInput_f32 = 1000*arm_sin_f32(PI2*i*50.0/Fs) + 2000*arm_sin_f32(PI2*i*2500.0/Fs) + 3000*arm_sin_f32(PI2*i*2550.0/Fs);
: f, m, v: J* b+ U8 |! d2 ^* o+ U4 Q
& Q( z; P" @; |
1 Y( @. }$ z8 s+ N
收藏 评论0 发布时间:2021-12-10 10:28

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版