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

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

[复制链接]
STMCU小助手 发布时间:2021-12-10 10:28
之前做课设的时候接触过FFT,看了一些资料,没整明白,现在做项目又用到FFT了,花了点时间整明白了。但此处的明白并非把FFT的原理啥的整明白了,只是明白在STM32上怎么用了。开发环境如下
2 }* Q# d' X* p* E6 r, eSTM32F767IGT64 c& @% |) o* z) I! m( ?  \
Keil5.21
0 i' p+ s& \0 ?: W/ X2 r' PCube MX4.243 K7 \4 F) m$ U4 j& w2 B( ^& t
arm_cortexM7lfdp_math.lib, R0 w# h8 N1 l3 o, G
正点原子阿波罗开发板$ ]% F9 N) M+ x* V, E. `- Q
4 D* X" |" D- U5 y% p
准备DSP库
, s/ N) X% Q" H. m& @" s& D% N# J打开下载的固件库,文件名为STM32Cube_FW_F7_V1.9.0,
' D' n" d6 L; G$ ?8 L, V. F3 h6 L: i; y9 Y6 J4 K
20180311111030987.png
0 J+ v: M2 S. D% }: x; X

0 @2 h; v( {6 W- d' _0 HDrivers文件夹下,CMISIS文件夹中包含上图所示文件夹,DSP_Lib和Lib是DSP库相关文件,其中DSP_Lib又包含两个文件夹,Examples和Source。" T6 @4 \! R$ x5 t
Examples 中的文件如下(这些是 ARM 官方提供的 DSP 实例):
. ~( f$ l5 {7 I' B" L2 z$ _0 u) e# O+ ?; L+ u
20180311111810371.png

* t) a6 v8 Q8 c, b* D
0 A' x7 n) }" |  U* w/ s  }Source 中的文件如下(这些是 DSP库的源文件):5 F, i. h* M! t9 W" l3 u! e- b) S
; @! y& M' C3 w- g5 C
20180311111958592.png

- g: F3 X. C0 y; C
" N; Q! y5 m( }  {源文件不需要添加到工程中,真正需要添加到工程中的是官方提供的DSP库,文件格式为.lib。库文件位于Lib文件夹中,有ARM和GCC两种开发环境的库,我们选择ARM。如图所示。6 W0 d+ S: U# J1 B
3 M6 M. b% `! H9 v) P( ]
20180311112424199.png
7 p; s3 l7 V. ?0 `! ~1 A

7 S( G/ ~# n3 \+ H7 v库文件有好多种,关于每种库文件的说明参见官方说明。 CMSIS DSP Software Library。该网站上有详细说明。如下图所示。, z% m* `1 p; Y, W  A

& B& P' d: l  ^, q2 ^) b
2018031111274971.png

( @4 d8 F% v+ @3 S
8 A: m+ ~" x6 o- j! i; i8 h/ C确定了用哪个库后,添加到工程中。我的工程是用CubeMX建的,因此添加DSP库的时候在软件中操作,勾选后自动添加,如图。3 X7 S+ q# R+ M: y; g( U5 [

+ ]  K" n9 ]  S, c# ~: c
20180311113253946.png
/ Z$ B( f* [3 r9 g1 w* j0 `9 N

9 z' c8 Q8 ?4 u7 G) E下图为DSP库已添加到工程中。& i" R) a$ Y$ M& d
9 J: Y+ V& y  E; M$ v' x
20180311113319114.png

0 H, ~* ^3 w; [# H0 Y1 T% T& c9 G
9 `( \4 R  P  ^库添加到工程中,在需要用到库函数的文件中引用头文件,#include “arm_math.h”,即可调用所需函数。
! S$ ]; |9 Y) Q/ s
" f0 [; y; R* g& x% j. f; l2 o' A
20180311113402949.png
! y/ d: }% H8 G& \

4 x: q, X6 E. @. [+ ]函数说明
& n% b' `9 }' S/ q% e我用到的是实数FFT,即rfft。相关函数参见官方说明。
2 Y2 l* v& V* d* p2 q0 R函数名中f32代表32位浮点数,q31代表32位定点数,q15代表16位定点数,q7代表8位定点数。
) D7 I/ `0 ?) U' `% |( _arm_rfft_fast_f32是FFT实现的主要函数,函数原型如下。
: t9 d' u% |  R3 ^' S6 q( w) _, E( y$ U
2018031111470032.png

) n) W. O9 }- i7 j# @' \: T
4 \+ y% u& k! w' F' K) n( WS是 arm_rfft_instance_f32 类型的结构体,p和pOut是输入和输出的缓冲区,ifftFlag是变换的标志位。
: i) \( ^5 \+ R& P/ G另外还有一个实现rfft的函数 arm_rfft_instance_f32,函数原型如下。
' F. Z1 z6 B' u0 L& P
' U% T) b$ ~. Y) {8 {7 k/ r
2018031111510511.png

: ~8 k/ N# P. C. z$ L- L( ?, _) K& w5 q' Q
官方不推荐使用此函数。“Do not use this function. It has been superceded by arm_rfft_fast_f32 and will be removed in the future. ”
5 |1 N0 q) k% A3 R0 n6 `9 g除了FFT函数之外,还要用到一个函数对arm_rfft_fast_f32中的参数S进行初始化,该函数为 arm_rfft_fast_init_f32,用于 初始化结构体S中的参数 ,函数原型如下。% D+ f2 ]; \. w7 M. G, n8 L0 d% ?

1 W$ K8 M6 r, n* H0 U* |4 n" {" `" ^
20180311115611796.png
8 p  O1 i& \! ~# {7 U

4 v9 y& L; ~- v0 L% V5 z7 Z) p3 [另外一个重要的函数是arm_cmplx_mag_f32,计算频率的幅值。函数原型如下。
; S' g2 u: c' |) O) r0 J
1 {6 Q+ E9 E- Z$ Y/ s( ]
20180311115858812.png

, {# D7 w8 M2 \. D9 C$ {
2 D- r- r2 }8 T5 [7 [+ D代码示例  M9 |% f+ v0 v; g3 a; V" y( J
  1. include "DSP.h"
    9 n: z, f% l4 |
  2. include "arm_math.h"
    ' R) L+ i2 W4 n, N" S
  3. define NPT  1024  //1024点FFT
    " \; `$ ?! q0 k- c# R4 [! ~% `
  4. define Fs 5120  //采样频率 5120Hz 频率分辨率 5Hz+ C1 L/ h/ K8 z( p& ^
  5. define PI2 6.28318530717959: t; D* s! @- Z9 j2 D3 \6 I
  6. float32_t  testInput_f32[NPT];; L2 L9 y  E8 Z7 Z1 H1 j
  7. float32_t  testOutput_f32[NPT];, L0 x: m2 Q. c
  8. float32_t  testOutput[NPT];# t: n- h& M. u% }, `" U
  9. ( j* l+ l: }  v2 Y8 I, C4 B. R
  10. /* 4 n8 i3 S3 ~8 K+ H5 C) c
  11. ********************************************************************************************************* " a& ?2 n3 {% U. _+ U# B
  12. *  函 数 名: arm_rfft_fast_f32_app
    ' F+ c+ f7 H" N9 n# d
  13. *  功能说明: 调用函数arm_rfft_fast_f32计算1024点实数序列的幅频响应并跟使用函数arm_cfft_f32计算结果做对比
    4 T, L: }$ R+ Z& G1 W: {( V
  14. *  形    参:无 ; c. m' `- g) N2 @: D
  15. *  返 回 值: 无 ! Y6 p  {  i1 M6 E* d. P( H1 V4 @& @
  16. *********************************************************************************************************
    1 i3 [+ Q; S) C! y  }
  17. */ : b% ?4 P) n1 C  c4 s
  18. void arm_rfft_fast_f32_app(void) : a) e% V. l) B( S- X  h
  19. {
    ; O- w) `4 e, B- q; d. w+ Q
  20.   uint16_t i; 0 E( e1 O3 K9 c/ z& @% ~6 O9 [' r
  21.   arm_rfft_fast_instance_f32 S;
    1 B; X, ]2 n' ~; I6 K0 E6 |

  22. ! [2 Z" O3 j6 Y; C4 f5 e
  23.   /* 实数序列FFT长度 */
    * Z' M- c5 j' S) M, y
  24.   uint16_t fftSize = NPT;  
    ; ^  e$ P) r. O4 Q
  25.   /* 正变换 */
    # r, i) ]! m( e6 P
  26.     uint8_t ifftFlag = 0;  
    ; M& T# x0 n1 T% F4 B
  27. 6 ~( x. ~9 v3 Q' O
  28.   /* 初始化结构体S中的参数 */
    . `/ a# k* k* H* K0 C3 F' y
  29.    arm_rfft_fast_init_f32(&S, fftSize); / |1 l5 k1 l. L1 a' z+ \4 A% n5 b

  30. & V( q) q0 B& ]; |# j/ h
  31.     /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */
    1 o; `  ~& ^$ ^* l; o
  32.   for(i=0; i<1024; i++) $ X! T' e* [9 B
  33.   { 8 p  J4 t: ]  x9 O
  34.     /*3种频率 50Hz 2500Hz 2550Hz */
    2 U* }9 P8 o# I# u4 I7 M* [. k
  35.     testInput_f32<i> = 1000*arm_sin_f32(PI2*i*50.0/Fs) +
    # ^; e5 \' y5 r2 N1 |
  36.                </i>2000*arm_sin_f32(PI2*i*2500.0/Fs)  +
    , u/ v5 g- l. C  Q) A* B
  37.                3000*arm_sin_f32(PI2*i*2550.0/Fs); : e* t% s: G2 Y1 F7 k; `
  38.   }
    . J$ I4 M' O+ V# c: {' ]+ ?

  39. , k" N1 g8 V3 F, [8 d. e
  40.   /* 1024点实序列快速FFT */  2 f& B  i( Y. q8 X
  41.   arm_rfft_fast_f32(&S, testInput_f32, testOutput_f32, ifftFlag);   M2 B' |: I4 |; s, ^& o  m% Q
  42. 8 t. O5 B0 K! b' s, X
  43.   /* 为了方便跟函数arm_cfft_f32计算的结果做对比,这里求解了1024组模值,实际函数arm_rfft_fast_f32
    ( ]/ I/ O; L. ]5 q& R$ `
  44.      只求解出了512组   ( j1 j$ s+ W; j3 A/ e' b& Z' U
  45.   */  # w# k9 D' N% O1 g' a! n
  46.    arm_cmplx_mag_f32(testOutput_f32, testOutput, fftSize); 8 r/ c, p, B  m
  47. 3 X7 W% D0 }" B! M. K
  48.   /* 串口打印求解的模值 */ 7 O8 e" p  e7 |9 q. c
  49.   for(i=0; i<fftSize/2; i++) / F2 }2 @5 L* c* g# A
  50.   { $ }" J  Q9 b" s0 P0 R7 {# d
  51.     printf("%f\r\n", testOutput); 2 l: S8 [9 {# z* r
  52.   }
    $ x- H5 i; _9 q4 ?0 p, f! e: r* H
  53. }
复制代码
0 k" m; H6 M) U7 G* U5 u3 d9 w6 G4 z, L
结果
0 i9 Y! i  J8 L2 a; ^8 m在单片机上运行,将串口助手接收到的数据保存到TXT文件,利用matlab进行分析。9 C' B/ y; G7 a6 `% N
/ _- ^5 ]6 y" Y- s
20180311120547219.png
$ A2 d0 W* I# n' n" I

& @+ H& D6 Z3 M: F: ?  V% J
20180311120659401.png
* e( v8 w+ f  W+ X+ E' p: I
3 m7 V2 l4 W7 P2 e: k
20180311120749658.png

) J; u0 Q2 R& V
6 R& z( z5 i' `# I# ]* ?: y8 B% f& J8 B% O8 K2 a
对数据plot画图,结果如下+ o. P4 r# Y, h- s  g: v- C

2 ^" p+ m8 P/ Y/ i
20180311120824877.png

0 q, [  @! w. S- l9 y) c
9 c' T; Q! h8 ]; h( z- d5 g1 i" O% L可以看出,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);
+ u/ Z0 ]* ~4 ^; @, c4 L: Y! S+ q6 d& q- E9 R' M

; b6 e7 R2 _3 H& O; U

6 E; T6 V( [6 R( _2 }
收藏 评论0 发布时间:2021-12-10 10:28

举报

0个回答

所属标签

相似技术帖

官网相关资源

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