请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下+ x8 v/ v$ S) ^6 w$ c
STM32F767IGT6
* I2 \4 j6 q5 _Keil5.21- i# {' X9 M2 E# A6 q: O7 T: N
Cube MX4.24
' w# X5 D3 ]) H3 `0 n2 J2 M) m0 K/ `arm_cortexM7lfdp_math.lib
2 N5 G; L  H: q6 L: X正点原子阿波罗开发板6 ~( t) N3 g2 [$ c7 Y7 K8 d9 q
: y2 [- D' p% m5 h4 @9 x
准备DSP库( ^6 x# @: [& k# F
打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,
5 A5 I6 g( o+ S8 U. K3 T4 ^: I+ r7 O7 W: ~$ j& f5 p0 G% b/ x
20180311111030987.png

$ X, i" {% m& p: t# O* e& j" R# R+ z# \6 P4 f1 R
Drivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。* f) `+ ^$ a0 C8 }7 i( O0 Q, a
Examples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):: a5 K# e" g" G  \

# u7 U, |3 W5 |( b
20180311111810371.png

; I- M4 U( s0 X9 O+ S# _; X- |3 Z- H) f
Source 中的文件如下(这些是 DSP库的源文件):
& `! G) ~8 h* q. B* y7 t9 ?' y) M
20180311111958592.png

9 Q+ h5 f& z% @# o
6 w+ @& h, Y3 {5 S0 x0 G源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。
3 W0 @- b: D  q& `! t8 j; o5 ]0 d4 {! s& m: q  t! f
20180311112424199.png

2 R' ~& K" T5 \6 ^& ], W9 M% s' @) w/ F2 X$ P% _0 X( ?
库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。. o5 `9 k  f; D; V% Z

2 Y. z( _. K/ c1 d$ g. D. n
2018031111274971.png

% x! s! Y2 u# B! H. ~: U4 r6 m) Z' ?3 f# i/ L4 j
确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。
0 Y3 n& a- A& }" m, K' B0 q( X, p: J, a0 b- U7 t, z  Q
20180311113253946.png
, Y3 B7 d" d7 h6 o. B* I' _0 |, \

, z' j: o4 ?; u1 }$ A下图为DSP库已添加到工程中。
8 z. ]* @( j# X. d- V: Q5 {0 T* p# n% W1 b/ n  `, Q. `9 ?8 N) Q
20180311113319114.png

9 _, V! N, q- k" i7 n* J+ p6 ?
; T# _) z1 l; u9 x: M; @库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。3 W  }! r3 {$ N& l+ Q$ R
4 N4 [& x4 P& U7 ?! R
20180311113402949.png

6 P# Q3 L: O. O" |& N& o1 L4 [
3 V6 j9 p# @1 j函数说明! [% a$ W% a6 O1 b4 y! q' F; b( _7 c
我用到的是实数FFT,即rfft。相关函数参见官方说明。
! D  |2 y+ O0 S) J5 X8 p2 u函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。' \$ d5 G* r, U9 o$ N. q9 b" m
arm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。
+ P: T% }9 R4 I6 t4 n( K2 R: T' q( E/ Z' \, D
2018031111470032.png

) w; D3 k$ i2 }1 k  ?2 q
+ i6 J7 I# @$ nS是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。: W4 I( N* F6 @4 [; t1 I
另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。
2 c* O+ _4 n0 `% y& f8 A/ d# s- Q! T* L, j4 Z5 ~  C) x
2018031111510511.png
8 {- S) J/ \3 Z: |' U; I

& c3 M) n5 u. E. x6 H' Q- \官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”! q) M% b* l6 N! u% @8 ?4 y
除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。
" [* Q3 [/ @4 q4 M2 a4 P9 B9 [. Y: t/ s2 G
20180311115611796.png

( b; E: J7 t0 n; l* Q' W
! n8 P- m; H. o0 h' h, h$ e: g另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。
3 v5 q, a6 h3 f2 M, H
+ s+ D  |$ h/ {1 j
20180311115858812.png

* u( o  l  X* m; N0 w0 e/ R$ F7 q4 r3 F" w  |
代码示例
$ ^; V5 o# a$ O% k3 [' `  X, W
  1. include "DSP.h"
    * j% u- K" E1 p- }
  2. include "arm_math.h"" J+ ~. O5 u' f7 f9 P8 \# l
  3. define NPT  1024  //1024点FFT
    5 M$ ?) }* {) ]2 D  U$ m
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz
    . S8 u+ q- p6 r8 d- _. d  l( ?
  5. define PI2 6.28318530717959
    ! {- ?# j6 k- l2 H
  6. float32_t  testInput_f32[NPT];; {9 O) W' C7 w0 c4 I* G* [
  7. float32_t  testOutput_f32[NPT];
    8 Y8 J6 Z  i& P0 p( ^5 {( c5 e
  8. float32_t  testOutput[NPT];  i) z! _& S  a4 L7 Z6 d

  9. 5 [' A. q. x; a/ j
  10. /* $ @  @1 B7 y: V4 I2 m
  11. *********************************************************************************************************
    : N$ K/ J; _4 [6 M1 _6 E
  12. *  函 数 名: arm_rfft_fast_f32_app 9 k: O- R* F* L6 r- |; M' C
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比
    9 t2 B, ]% B; y; ?9 {$ A
  14. *  形    参:无 0 K) F$ S; V9 p0 q4 y4 }4 Y
  15. *  返 回 值: 无
    6 [* x' a1 H9 d9 `8 {* w
  16. ********************************************************************************************************* ; p7 p# ?& c& k; Q4 ^
  17. */
    / U0 J& U9 S, ?
  18. void arm_rfft_fast_f32_app(void)
    # c- N! E/ C/ Q) B. s3 C7 P+ b
  19. {
    . ~" i& W) |1 v( Y+ c1 S! F
  20.   uint16_t i;
    , y& t  R! `9 w' x* e, s* c
  21.   arm_rfft_fast_instance_f32 S;   ^; N+ [- _! j" t8 M; ?
  22. ) D5 y3 s2 ^, w! h
  23.   /* 实数序列FFT长度 */
    , {3 }- ^% `" @2 C4 D% Z$ R
  24.   uint16_t fftSize = NPT;  6 W. F  r) t/ R, }
  25.   /* 正变换 */
    $ w" k. b$ ~. c+ i* b. L6 x' u
  26.     uint8_t ifftFlag = 0;  
    : Y7 i5 u9 @* P2 ~1 Z
  27. 3 I& J* e) Z& X; v
  28.   /* 初始化结构体S中的参数 */
    0 o. a* @# y3 `! i; l( [
  29.    arm_rfft_fast_init_f32(&S, fftSize); 7 d# J2 c- u, V; B$ ?

  30. ' B9 t' \) K" B' }3 Y( u
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */ 7 F$ C; o5 y# d4 A' j
  32.   for(i=0; i<1024; i++) 4 [$ z* Q3 o1 T' J. X* z, Z& B( D
  33.   {
    6 o8 p2 ~7 [; _" g; y! J
  34.     /*3种频率 50Hz 2500Hz 2550Hz */ 1 ?0 Q" s# }5 k! \) z) m- L% b
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) + 4 g: z' A  L, _, i) i
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  +
    5 N1 E0 D+ B7 u6 f: L; l
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs);
    4 \3 @/ m0 P0 n( o
  38.   }
    ) @& \% Z) `% ?4 U/ ~

  39. 8 ]" c  t3 Y2 i! g6 d' L; U
  40.   /* 1024点实序列快速FFT */  ' g1 D$ M4 ~8 Q. Q+ Y1 T/ J
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);
    9 h0 Z6 l# A- y! y" f8 N
  42. 9 h! q" u) `1 }3 d$ P2 C3 m7 u
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32 / K+ x! @9 Y7 a/ }& f
  44.      只求解出了512组   5 ~: B% U% A. p6 X, R: _
  45.   */  
    + I3 w# [5 B4 R( W* E
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize);
    # z  u& J4 q: j4 ?. e6 B
  47. * g$ m2 v2 c) ^, u$ C( M/ Z
  48.   /* 串口打印求解的模值 */   |$ R9 [8 }( D% i4 }: `
  49.   for(i=0; i<fftSize/2; i++)
    . s  W' I% N8 b5 W. o% H, _. l3 n
  50.   { # p! M: p6 J( r, f9 Y9 B$ c; ~" L. b" h! ^
  51.     printf("%f\r\n", testOutput);
    ) @& \0 ?# ^( i: J
  52.   }
    ' `" h# I  ~# }. h
  53. }
复制代码
3 }8 q2 f! S5 }5 v5 c
结果
' h( U1 M! [) u; p在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。
$ L1 [3 _1 i+ L* @1 S
5 I0 e' r1 W1 |5 E" L/ Q
20180311120547219.png

8 `; p% p, o& b$ g, o5 Z7 S! H# p7 s( p+ x( s
20180311120659401.png

$ h, o: ^: O, C* u- A% ~
2 R+ }# O1 a9 _" x  q5 h
20180311120749658.png
! n$ m* q& s0 {" J9 Y3 \
* Z9 {, Y) p: w8 X* Q+ _# Z+ v5 j

6 a* L3 M( G. V) L) n4 S对数据plot画图,结果如下7 O3 ^. n" G7 @" P

( R  |. m1 |. ]8 E0 K# p
20180311120824877.png

6 C8 W7 Z7 l; A# {& s# C4 G0 v) A& C/ g
可以看出,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);) ^! h' N' X! I! x7 p+ e

& z/ r0 ]; C! y7 \9 d
+ _; z1 b& \# y! `% _
4 A! A6 \; D+ U
收藏 评论0 发布时间:2021-12-10 10:28

举报

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