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

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

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下, X% B- m5 X3 ~" [0 x, V
STM32F767IGT6& o/ m: G) X  D1 X1 q3 b
Keil5.21  _/ i# j7 ?& e' q1 H% O
Cube MX4.243 i7 ~; C; l& |& ]; s5 l$ H
arm_cortexM7lfdp_math.lib
, i, w9 |- c) s正点原子阿波罗开发板( a+ x; m7 d9 l# h
1 a( z8 a3 {# D) C) @
准备DSP库
% J% d+ h' Q& w" l打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,, ^5 L' _9 d# o" A1 m2 h# r

* [+ B+ [. z$ F1 b1 @7 N+ a
20180311111030987.png
8 {8 Q. `  d! z! \! U& m' K
3 C/ R8 A0 n) x2 t, W4 E
Drivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。
: ^6 R0 X& |! u& E4 IExamples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):& I; N7 K* w% V  G
; D7 N) [1 b" j" X8 ~
20180311111810371.png

9 Y  g, b9 E" ~) Q5 o( K! A+ C: w% e, r( V- ^5 V/ h* F
Source 中的文件如下(这些是 DSP库的源文件):
) H3 o( q0 R% Y. A3 v6 l4 D. C8 v& r4 c
20180311111958592.png
8 m& L3 m3 P  V- c- i' v" c1 o
( G2 f3 ?1 N" P. R0 E1 U
源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。
  L6 x$ d* F5 G% u# q* D0 D2 Q! E* m/ r) h
20180311112424199.png
$ p: q/ U, ~3 @4 U1 p

. u% I$ K( _* G9 Z5 i库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。
. n" U7 n7 z& f: ^2 G
, P6 k$ ~. K0 P
2018031111274971.png

# X/ `# R! Y' O9 `6 C
( e7 W2 S; K/ n' S确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。! s7 y( X& I( [6 M3 u9 z8 z( v

( p' o8 ^6 h9 w2 q4 I" a' u
20180311113253946.png

* G$ z) Q2 m1 I
& J3 J6 ?5 x9 c0 ?0 t% k1 @( i4 x& t下图为DSP库已添加到工程中。
+ H+ |0 s2 B6 M& O: z# d: @5 U- j5 Y6 u9 x; z
20180311113319114.png
2 N3 f" O3 f4 H2 f. g. n1 O: d

1 i1 @: B! k- v# u2 }库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。
5 E, ~* E/ o1 o  u( Q* ]1 R9 W, l2 c. D6 x9 s5 C
20180311113402949.png

4 l% g: D4 r/ C; l! C% B/ H( M4 A  t/ g% @  q) Y
函数说明0 n$ Z% p" }+ N% ^, m' @
我用到的是实数FFT,即rfft。相关函数参见官方说明。7 Q  @0 ]0 j1 Q/ b/ s0 l
函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。+ r/ f  o+ H: {" {' g: P$ L
arm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。0 Q) f  n4 d$ T" t3 k

. u' b8 A- r/ P: f8 G
2018031111470032.png
! P6 Z8 h, s! x. D4 @, I
& |; p- Q* i9 z( c
S是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。; Y! d$ x7 f5 r0 |  K
另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。
' y+ H6 e6 `8 M  [5 ], C+ e$ M1 |% O
2018031111510511.png
$ H9 l, _. u) [& b! {

! A: @! W9 a' k7 a+ [1 ?$ Z5 \官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”. m/ k. }" A- o; a9 p0 K* P1 x( M
除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。
4 F; C0 D+ J0 ]6 r% ]9 u! U" N, A& L' F/ V
20180311115611796.png
8 b7 L- ]  _. p: i9 ?
8 C; x. U# W& {8 V% U
另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。
3 B: T0 L1 W2 j6 c: Z' w! O, Z
; {' i  |' y, H% t$ B
20180311115858812.png

8 D. |8 o: @' M. V# O' r  A/ ~$ t+ `9 Z. v: C$ ^
代码示例
0 u" ], s- q; ~% z
  1. include "DSP.h"
    8 e" |' u# Q, A3 E1 [
  2. include "arm_math.h"5 X! f7 Z+ G3 F* v" e: N" z. l
  3. define NPT  1024  //1024点FFT+ V- `3 I+ _& e  e$ {- ~
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz/ l+ ~+ |0 d% @+ R/ y. s( i: P
  5. define PI2 6.28318530717959- d7 Z0 ?& G) _! p6 Q, ]6 Y. n: O9 _
  6. float32_t  testInput_f32[NPT];. y6 D3 @& r9 s$ c* n: x! Z
  7. float32_t  testOutput_f32[NPT];
    $ v2 x; R4 @* _- v0 y! w3 ]
  8. float32_t  testOutput[NPT];- y6 n7 ?! j* p. ^

  9. / D& b5 G+ ~: s2 O
  10. /* 5 |- u! `: h% R2 E7 Y/ `
  11. ********************************************************************************************************* ) v7 W8 \" z! J' P% Q! R4 h( j! B
  12. *  函 数 名: arm_rfft_fast_f32_app
      f, f2 {$ E" m9 p4 W1 u! s
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比
    * X$ p; _* y+ f. l
  14. *  形    参:无
    4 S1 J) @- T+ x4 Z$ }% M0 b
  15. *  返 回 值: 无 " `  F# \4 N& f
  16. ********************************************************************************************************* ; V6 Z% D2 S. Y# Y1 s6 S& c5 t* C
  17. */
    6 Z' N; u( Y" v7 P; L1 k
  18. void arm_rfft_fast_f32_app(void)
    5 J- G6 i. h9 n6 b. i+ m; f
  19. { ) a2 V3 X5 {9 ^' m$ p
  20.   uint16_t i; 0 D1 K/ Z+ b. {8 w. A& k, R$ g' `( J. Z
  21.   arm_rfft_fast_instance_f32 S; , d# O8 `* L3 Z* a

  22. % D' _+ M: O4 {7 i& C+ e
  23.   /* 实数序列FFT长度 */
    8 [7 r( m! }8 O
  24.   uint16_t fftSize = NPT;  
    4 c  h; M+ A5 X* F" R) N; v8 @
  25.   /* 正变换 */
    + r' w; W7 B" _' g" c1 ]4 k: ]
  26.     uint8_t ifftFlag = 0;  * N" J0 |" T# b# a5 b" m
  27. ; u9 b$ T1 j' p: K1 F' ]
  28.   /* 初始化结构体S中的参数 */ , r4 m; F$ t& {, ?+ a" W
  29.    arm_rfft_fast_init_f32(&S, fftSize); - A4 K6 g% I# T% x9 i

  30. 0 r# [  U. ?9 `- a; N: S
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */ 5 k. p8 E7 z! e. K+ H5 \& X! m
  32.   for(i=0; i<1024; i++) 5 r- s# W* t/ ~+ o
  33.   {
    3 _0 o# i1 v: f  \7 B
  34.     /*3种频率 50Hz 2500Hz 2550Hz */
    ) G: Z! U* m) B$ X# ?  B
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) + % z4 g+ ~/ Y; r# F! ^# a) p
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  + 1 w! q+ g" k/ g) B# h; v. M4 X. S
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs); 1 ~) o- X- D: M
  38.   }
    + x1 P$ B' h$ ?6 X, z; w& H% b

  39. 6 X8 t4 ]+ J+ {( \) O9 u7 h
  40.   /* 1024点实序列快速FFT */  ' x9 F% W- F$ B, Q4 b( T5 Z- O
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);
    4 l! {( O; r3 B. T

  42. 7 n( F2 \* ~2 z7 M& J% W; b5 z' i
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32 $ G* Z& h8 k7 Z/ u" D
  44.      只求解出了512组   
    6 k7 |5 U: q4 D& \
  45.   */  " `- R/ g( o" I# i
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize); + E! C" F$ g  E/ z6 A4 i# X" B7 T$ n
  47. ) M  I# K; d5 a/ k
  48.   /* 串口打印求解的模值 */
    ' d0 Y8 w8 A) |2 J) q  Z" ]1 Z% V
  49.   for(i=0; i<fftSize/2; i++) 7 h- z6 h& Q" i( f/ |# ]& _, X
  50.   {
    9 i2 [! ^' k5 w, r: |2 ?4 e2 W6 A
  51.     printf("%f\r\n", testOutput);
    9 N  p) b, p& R2 G+ ^
  52.   } + L5 l* @- I2 G
  53. }
复制代码

/ E7 f1 `; `' r5 {9 I1 C+ r结果: }# a* V5 k5 m2 r) T" \% h2 n( g
在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。/ }% L4 ?4 u% q" {1 J
4 z% k0 D$ _" d4 n8 J
20180311120547219.png

5 \( b' {: Q+ m+ o3 n' b9 i, ]
, M4 H) A  C/ D: S$ i" ]
20180311120659401.png

+ G& L8 q+ u+ t( W: \$ ?
" z( Z* m0 O& I: a) o4 a& R
20180311120749658.png

) D. A9 D! L0 T5 C' A3 J7 b! T* V2 O
+ {3 w! P; K. n9 b2 m) z3 K  n( F: o( g
对数据plot画图,结果如下
, x: [/ u$ G2 t; W( f
6 N  `5 F$ m" j+ ^7 Z9 E$ X/ Q! Z
20180311120824877.png

# t2 G' I, _5 o- a- T( K# n3 a, H. n8 ?
可以看出,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);' X8 I* l8 |4 c+ O+ ~+ n1 g
( J5 f! l8 g+ K/ y0 f# C% B
! p! M. F& R. m, J; X$ g
# {: w) O& P! I/ v3 X' u
收藏 评论0 发布时间:2021-12-10 10:28

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版