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

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

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下
" N1 b% d  p7 S7 ^STM32F767IGT6+ o& T/ k4 d* {2 ~2 h# F7 }: H* K& u
Keil5.21
/ f4 X6 C  h* p+ }* Q3 c; oCube MX4.24) y  Y. P! k9 {; J8 ]
arm_cortexM7lfdp_math.lib$ C# P7 {0 B$ c1 @/ n( b9 l
正点原子阿波罗开发板
8 J: ]0 ]; a9 T0 L: ^4 K& {2 k0 n- p, V1 d0 \3 t
准备DSP库, c8 L1 H7 M3 l4 z
打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,
) n- `/ s) h3 R) _, N; r- H
. l% z' R4 |2 r& y2 P: o, V
20180311111030987.png

$ c( |; {/ [: C( h$ T' \8 j  M
+ I5 m8 |2 k! }Drivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。6 S# C3 K' t9 n, j6 F$ S4 W
Examples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):; o& T7 ?& P% K) I
2 G( X8 J5 h- |% g  C5 x4 K  [8 x
20180311111810371.png
0 S& c3 c" A# j3 ?% p7 Y0 J7 X

4 b$ N5 ]8 l: n  `! i, X  jSource 中的文件如下(这些是 DSP库的源文件):+ a+ e' t; M8 `0 ]2 h5 w& o
+ V" E0 w, V) K  }* [0 E
20180311111958592.png

& A, w+ i! I- x( g* L% C8 b' k0 [- r1 X' w* M: ?& @
源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。& m/ G, |+ p$ b7 n4 D2 W5 I/ R
/ h, L* f# W7 g# t8 `& N4 Y6 C$ F
20180311112424199.png
% w/ t* ?1 p, m5 {$ f
. n1 C% N( C  S, u% }! M( [5 \
库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。
0 t+ c7 f7 k2 f* s( G: e9 N& N" \3 j5 _' H( X  b5 h2 ?
2018031111274971.png

/ o' ^2 l/ t# ?1 f3 e
% f0 I9 Q+ s: Y% H# T确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。
3 f' S; h& X$ j
, S' W& {+ ?! |1 r
20180311113253946.png

: h8 b' j4 x$ W
0 y! d$ `8 c% a" p' x下图为DSP库已添加到工程中。+ f+ t  I. c" C. H
" W7 j, s7 E1 I" t6 V1 u8 d" @
20180311113319114.png

2 O; W7 o" {9 ^0 o- e) j$ e" a, c6 [
3 H$ D5 c6 P9 O库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。. K& H4 `; }1 H; Y8 H8 s4 b/ ?3 M

; @+ T- u7 ]  F1 N) S; D* t
20180311113402949.png

0 G9 e+ p, H' O/ R, M, |$ o. {" N; b5 ]3 P$ s9 @
函数说明6 y- z, C0 i: H. u1 ?7 c
我用到的是实数FFT,即rfft。相关函数参见官方说明。! R6 I# y9 a7 G! m1 ~* o2 J( Y
函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。
2 [% \$ z1 }, w( h5 ^arm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。0 k) X% R+ a0 p1 i! V
  `+ @/ `2 {+ B5 t& i# a" i
2018031111470032.png

. Q9 u; B# V; I# ?
- v7 A5 U9 G% C6 US是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。
* t. U! C2 [: e* U另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。) M: j# c" u+ R0 k3 ]+ C
( r  T" i9 T: M$ L9 b
2018031111510511.png
' b" H' o  G- v% {/ n- \, M! Q$ F
) U" q- c( |# {7 u1 x# `% g
官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”
: r1 S0 [5 a& U  y除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。. s5 v  M# ^' @1 U& d
0 ]9 c  t# O$ [) I% _) q: H
20180311115611796.png

: w9 p* x8 C5 c2 ^; \9 P$ Z1 r* ~4 B3 d; X/ U  B9 `
另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。" y' r+ P+ _1 l2 u; @

! m$ f! I9 [6 M, a& m
20180311115858812.png
5 y: M( i" p) s9 e

) C) [0 z/ @. m+ ^代码示例2 |4 I( U. z+ G* Y+ s4 x/ [1 P
  1. include "DSP.h"- L$ Z/ {6 I" P: [/ R
  2. include "arm_math.h"! c/ U! b& E3 Q/ b5 c$ s
  3. define NPT  1024  //1024点FFT
    & ~$ M+ j% |$ H( {+ H3 \/ @9 C3 L
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz
    + P6 r* ~4 y  i1 c) z
  5. define PI2 6.28318530717959
      g, u8 v: ^5 ~# \5 Y8 ]8 w. _
  6. float32_t  testInput_f32[NPT];0 }/ Y1 ~, a9 P' `: ~
  7. float32_t  testOutput_f32[NPT];
    ; u+ E4 ^9 w) }
  8. float32_t  testOutput[NPT];
    ) c; B0 r( U% r
  9. 6 u8 ~! O3 A# O5 E& K+ _
  10. /*
    . T2 R6 P$ o1 i  ?
  11. *********************************************************************************************************
    , f6 f5 X6 c0 F, d' u
  12. *  函 数 名: arm_rfft_fast_f32_app , A! V* `0 F% L1 q+ O& f4 |3 v. I2 S" Z: H
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比 5 u: i" ]; m$ _* F
  14. *  形    参:无
    1 r- H: P' A3 Z
  15. *  返 回 值: 无 ! Z; |  q+ ^0 E, z
  16. ********************************************************************************************************* ( U8 b8 T) u. |) i* N% B
  17. */ $ t# k/ g0 v) z7 k& E0 O& L& ]
  18. void arm_rfft_fast_f32_app(void) $ O* }% ?' A( L/ }- Z! M
  19. { ) B/ p8 j6 R5 D  F; d
  20.   uint16_t i;
    . F) V$ n' f1 K6 x$ W5 D0 l; }0 L
  21.   arm_rfft_fast_instance_f32 S;
    2 \+ g$ [6 B9 b6 L

  22. + F# y9 b7 P* e. J4 m% V
  23.   /* 实数序列FFT长度 */ 1 z. y+ ~; f( V
  24.   uint16_t fftSize = NPT;  % n( B9 ?% W6 t9 Q3 u
  25.   /* 正变换 */
    4 T" Q8 A" D) c' l
  26.     uint8_t ifftFlag = 0;  * N& I) ~( e% `7 I2 d# n- K

  27. 5 N& i6 B4 [/ x: x5 c
  28.   /* 初始化结构体S中的参数 */
    ( s- L5 s( ]* D! T. s, @
  29.    arm_rfft_fast_init_f32(&S, fftSize); * d! G8 Q0 x% T

  30. 6 }/ ?! v  K( |  X7 a7 @
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */ 8 u9 l$ Y0 |( |) V
  32.   for(i=0; i<1024; i++) 5 @5 q1 Y4 f0 i* \9 N
  33.   {
    : I, I% w# ?, p5 B
  34.     /*3种频率 50Hz 2500Hz 2550Hz */ # U. a9 l5 j. @$ l
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) + 2 m" B5 M$ s) Y- c# K* z7 F  e2 W1 M
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  + 2 E& v( P6 c9 k6 j
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs);
    - Q# _- P3 w; Y8 v
  38.   }
    5 B4 U/ c& a2 C0 h! ~% M/ B
  39. ) A# I$ {3 x. H$ h6 G& F' j) x  X
  40.   /* 1024点实序列快速FFT */  
    " _, P4 k. _, ]" O6 g/ S
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);
    , P. Q4 W  {- i5 V# h

  42. , B/ m, A1 `/ X) R+ w
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32   _  C7 S6 e" {6 E  C: u: s
  44.      只求解出了512组   5 }8 t2 o" Y' `7 u* a0 j
  45.   */  
    1 n( q, I* {7 y, ]
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize);
    2 P8 `! J" S, W2 F. a
  47. ; F' R9 K+ [6 N. B; c
  48.   /* 串口打印求解的模值 */
    ! h+ x; z5 F% t; a0 e5 `$ M
  49.   for(i=0; i<fftSize/2; i++)
    " G. W2 z1 {$ L6 Q* d
  50.   {
    / w. m0 ], ]* A' g5 [
  51.     printf("%f\r\n", testOutput); . S/ A% d; U, f
  52.   }
    # O# T4 b; i- @  u9 Y. U
  53. }
复制代码

. h9 U# l# @2 u8 S结果
' i* T2 U5 B; o# S( O4 w+ O在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。
& |+ L  B6 Z) V  x( O
6 r6 T) @( I( h9 u' k3 `7 ]$ N1 }
20180311120547219.png
; c; D- p3 S( u3 k

! D; E+ ^8 T2 R* e# C
20180311120659401.png

3 O0 e( d+ Z% U# \# M; g: u
2 f; @! a4 j5 f- Z% b  k
20180311120749658.png
- `2 K/ u# m* m0 ]

" F% m+ d2 ~4 }# T: S& g2 {, R1 M  P2 p* Q- b
对数据plot画图,结果如下* o# k# z& ~/ C) Z7 R6 O/ {, Z

* i1 c1 T9 g3 w( E" X
20180311120824877.png

" n1 C) \( D/ o# J5 v8 d' o1 ]2 W6 o  n8 ]5 T# ~
可以看出,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);
! B6 C* W/ C, [& a
- t; ?5 Q/ M+ f' d; H2 _6 C
$ H9 D! S, h6 F3 @& r8 \. a- |" e6 ?
* V1 M3 J' x* A2 p
赞 收藏 评论0 发布时间:2021-12-10 10:28

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版