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

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

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下
: P8 L, ^/ j2 K" X3 ^1 `: sSTM32F767IGT6
; N* I7 a9 J6 y) \% r$ @, PKeil5.21
2 P7 Z' I% M  F# g5 WCube MX4.245 ~4 ?/ C( U" ^+ j+ a7 X
arm_cortexM7lfdp_math.lib
  v$ o2 T1 i; G3 P( }正点原子阿波罗开发板
$ ]: l1 ]2 f% q& j/ L) L4 A- j. z) z) A9 [3 s, e
准备DSP库- B9 {" ~% ~0 Q7 T0 @+ A
打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,
& h3 r( b5 D5 v0 I* q+ C0 k
: @, |. L/ L: P
20180311111030987.png

1 U0 w0 P, Z7 v6 y! @4 y
) Q4 R' }! F' |! r, }& UDrivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。
; n  W$ u( l9 I. A) UExamples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):5 Z: p  [  C% ]2 j7 @( D
1 ]5 B5 {. n5 Q  y' h( T
20180311111810371.png
. Y# |; z' ]3 Z- ~2 U& X/ Z

2 I" {$ `. l0 L8 {5 jSource 中的文件如下(这些是 DSP库的源文件):3 }- N: I6 ?4 j0 s; t
# ?" k- T9 p( f: H9 m, W" g
20180311111958592.png
: K% P* O" P5 O7 Q4 |$ \5 P

8 |  S3 q( t" d5 c  Z7 k  n% l* ~  Z: {源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。
3 Y/ X1 C" W! u, _1 x6 q1 @) P" ^
20180311112424199.png
) M# F+ u6 V8 a* ~
% N3 K& E+ J: l, @8 _6 Z! K5 D
库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。* U2 M, O& x* Q7 _5 G
" W4 c8 d* P0 N  M
2018031111274971.png

: j9 q: g" Z1 r% Y3 |* H/ G% ?# A
' j# c. R) N7 G9 v" i% S# N确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。" x/ @" {7 F/ z+ i) O

  ?# F" i+ h6 B$ W& v1 x
20180311113253946.png

  H6 T2 V% o& C$ g3 x3 T5 R- E# a+ c
! r' @; B6 F6 b  I, |# U' Z下图为DSP库已添加到工程中。! n, x4 w0 Z/ f7 ?

) P. v1 U- ?" T5 [; Y% Q$ W0 M
20180311113319114.png

$ G* O$ P8 n. U$ ~+ Z3 L, X# ]0 ]
: j6 w# R8 e$ X4 @& e  b3 o库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。
- E! ?* P& f; f& i3 Q! ]* i! E$ o9 F( p! c+ `# K, x! Z7 Z- |
20180311113402949.png

2 G) t8 O9 \8 v+ O$ i  N
" L* v* m- r6 R( \4 Y  c: t0 F/ R函数说明
- K! m- n" k" d% ~0 b我用到的是实数FFT,即rfft。相关函数参见官方说明。
: h& {. L, A1 |* E4 A$ Q函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。
: ]+ v' N0 h3 b, y7 i' r& ^arm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。/ W) R, _3 Y  i* F2 h) L; U

- r5 k: \' x# y( O* h
2018031111470032.png
. ^: ?& z  t$ `, f

0 d" [% H4 t( _5 _0 q+ S1 aS是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。- r: r6 b. w( p
另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。
5 A5 E" k8 q$ g* t5 A6 v: R4 W
- n& U8 L/ R. Y. G7 D! J  o
2018031111510511.png

( ?0 s9 o9 D' I* h
: W- R3 P$ |" c$ ]& u( B5 l官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”
6 \/ W$ c1 c( a除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。
; v/ x! h; O0 i$ B5 Z
5 z- [" b" O- E7 c
20180311115611796.png

6 ]- T( o4 z. {& C9 X/ K7 q& A% A' v5 }/ B: h- `
另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。
* h( u8 B- |+ z4 F/ |. u' B7 T& M+ H, j2 y" V, ?
20180311115858812.png
; _, r% |! t4 N4 R1 x+ x: `

, H. N" c7 |2 L  H代码示例! N# ^4 E  a& q9 v; @/ w
  1. include "DSP.h") ~* q* z, e3 f- x# }* ?; Z
  2. include "arm_math.h"
    ; w+ s, K% A$ d2 ?8 H
  3. define NPT  1024  //1024点FFT
    9 k6 B9 s% N1 T& h3 s$ h# u6 V
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz5 ~# w; D' g  O* B  d
  5. define PI2 6.28318530717959
    " r- e8 u8 w3 |. ~6 O
  6. float32_t  testInput_f32[NPT];
    8 H& N  F/ c: o3 r
  7. float32_t  testOutput_f32[NPT];
    & }- f- Y# w0 U& c: f
  8. float32_t  testOutput[NPT];+ I) i! Y3 O% x. L5 k

  9. 0 n7 g, K- `+ S
  10. /*
    ! l/ _1 z; c( w7 m) N! F- t
  11. *********************************************************************************************************
    " m/ ]& Q9 I* L' y1 K
  12. *  函 数 名: arm_rfft_fast_f32_app
    $ k* _9 G  P% r
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比 ! J' ?( w: m. T  C( i' K) r, b6 T2 T  D
  14. *  形    参:无
    4 J. r4 w% }* L# S$ z4 v, Q  p
  15. *  返 回 值: 无 , M, |1 u# ^* e9 Y- V1 _
  16. ********************************************************************************************************* & U, Z8 `, k! ]  L; q8 t, a! F" V& l8 ]
  17. */ - V! u8 `# B1 f6 q" V# I
  18. void arm_rfft_fast_f32_app(void) # o5 j' i& f0 G* M: k
  19. { " c3 H, K- h- U- D
  20.   uint16_t i; ' Z+ I- O  d; C0 c; R0 l
  21.   arm_rfft_fast_instance_f32 S;
    ; q+ ]2 }! `: h0 [/ o8 J, k
  22. 5 K" b3 S0 R/ }8 z9 H
  23.   /* 实数序列FFT长度 */ ( W4 W1 w3 W' A- Q& n( j% H
  24.   uint16_t fftSize = NPT;  
    + `. A% F$ m3 o7 L% d( u+ v8 D
  25.   /* 正变换 */
    : K* u3 h, m  e+ N6 b  z
  26.     uint8_t ifftFlag = 0;  * p1 P4 F6 a1 L' _

  27. , \* E- J6 E  Y5 u+ `( E
  28.   /* 初始化结构体S中的参数 */
      \7 R+ N  }/ ~& |
  29.    arm_rfft_fast_init_f32(&S, fftSize); 8 k! S  v7 w- E7 c+ R- x
  30. + N; w/ j2 f& z
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */ 4 P" ?" \- @  g* p7 o
  32.   for(i=0; i<1024; i++) 4 Y; g( a2 C4 o# y
  33.   { : b# j5 x# `, V
  34.     /*3种频率 50Hz 2500Hz 2550Hz */
    , |0 |  W4 o: b! y: m6 A1 ]9 k
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) + ( p" D! B" c$ {0 l' B. |
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  + * d$ @' N0 @+ Z  x8 J4 a
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs);
    8 c" }* E2 s8 M7 i  Q  \: y; E
  38.   } ! l( U8 o2 F( I+ M
  39. # \* o* ^' _0 ~. y& f1 A0 a0 l
  40.   /* 1024点实序列快速FFT */    B& [; Y$ r6 o/ B; O
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);
    3 D, p7 R( N6 E+ q

  42. , ]4 ^5 h: E5 y1 K/ v
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32 4 h1 t1 \# v3 k2 f* x; `! m. W
  44.      只求解出了512组   
    3 a" B0 z) h# O4 R  o
  45.   */  , o, l, x& P3 n" U$ k. [5 D
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize);
    4 \0 v; B4 m! S; j

  47. 0 f0 K( h1 m/ d3 n; H' e: ?7 `
  48.   /* 串口打印求解的模值 */ ( Q8 [5 B2 p9 {$ Q/ R) R3 u$ w
  49.   for(i=0; i<fftSize/2; i++)   X$ N( V0 t! P7 d
  50.   {
    2 |' t( E( P, e& s( }: D
  51.     printf("%f\r\n", testOutput); 3 P3 k3 t% G3 e* F+ p
  52.   }
    ) I7 t- @5 Y" @
  53. }
复制代码
4 l4 V% t0 {  J: [
结果
! o* X7 t# a0 T4 `! z在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。
) M* m' J! {* W2 v7 R# P/ l$ B6 _) P: n- u( ]5 m
20180311120547219.png
, r/ _$ g5 l* K( p/ t1 F. B5 x

7 M3 ^+ u9 w" m# H( }" g
20180311120659401.png
( p7 w4 u  e9 H3 s

3 z% f# d6 l8 K
20180311120749658.png

1 K$ \4 q) J; X0 N0 e- y
. b& O3 H. {8 V) m# o* O" Q) r; M2 w
对数据plot画图,结果如下4 |: v, J- I, ]

" e- p3 X/ ^) X
20180311120824877.png
+ R  O( F2 |& n" Q3 M! k; [

/ C* }6 T, M% f  y% Y: a$ z可以看出,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& B$ ?/ W9 e' A' a% v( v6 d  H. k' e8 G/ T1 z
% J$ J$ n* J9 L% i
; I2 c$ ]) M0 U
收藏 评论0 发布时间:2021-12-10 10:28

举报

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