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

基于STM32的快速傅里叶变换经验分享

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:08
快速傅里叶变换(FFT)是一种数字信号处理中常用的技术,用于将快速序列转换为频域表示。在嵌入式系统中,如基于STM32的微控制器,实现FFT可以帮助解决信号处理的需求,例如声音处理、图像处理等。本文将介绍基于STM32的离散傅里叶变换的原理、实现方法和应用。2 W- E& [2 z& ]4 G0 R
: g% _6 B9 H0 I" R. i
微信图片_20240529190800.png / {/ W' ~& a; ~  F
8 W5 B  X: c5 W  U1 r
FFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:, {8 @3 O7 j0 }7 k0 f+ r! |8 h

7 d1 P% y7 h6 A4 Q4 S/ {* u
微信图片_20240529190757.png
# R) G3 N* b2 J
& n. D" N0 [, a其中,x(n) 是输入序列,X(k) 是输出的频域表示。
5 _  a& T6 B) J! r) H& g' l3 V7 i' t! `
准备工作:
4 S" b0 i+ ?0 Q, @+ L4 O. j$ n3 ^: ^% X8 c
7 V  ~" q: y2 f. I( x
微信图片_20240529190754.png
) }  Z3 h  B; a/ W* V" Q7 |8 e- |8 B: K
微信图片_20240529190750.png & a' m0 ^# e2 y) U
( S* K3 ^. l0 z
Keil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。! p3 U! B9 H) e8 a8 ~# @  j
% d+ C* ~" E  X3 o
因此我们需要在Keil中安装我们的DSP库。
" H7 C, c4 D4 X; @
  1. #include "arm_math.h" // 包含DSP库
复制代码

: H) v8 k7 T. |首先包含我们的DSP库。
8 r1 t; H+ ^  a* O) d' H; i! c7 H
6 h& H, t9 `+ Q8 ^: U" E
' y+ j; S! D1 q6 I
  1. #define FFT_LENGTH 100
    . L2 i1 s+ L5 @. b/ V: A  e
  2. // 输入序列: B  K8 Z# k) f. Z
  3. float32_t inputSignal[FFT_LENGTH*2];
    + ]4 G) K; j+ Z! N! W8 o
  4. ( E. A# V, i$ L
  5. // 输出序列,存储变换后的结果4 \9 q$ t$ A; \" |, w3 I
  6. float32_t outputSignal[FFT_LENGTH];
复制代码
( `! F7 c& ], x; v' m
定义FFT的的输入和输出数组还有数组长度( }9 U3 Y7 x( U- f
  1. arm_status status;3 i  q) w9 W% x/ j' }
  2.     arm_cfft_radix4_instance_f32 fft_inst;
    ; I! [$ X- _" u2 i- `# y
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32(
    7 g& R% j# ]% L4 q8 e/ G7 i/ }2 R
  2.   arm_cfft_radix4_instance_f32 * S,
    9 V$ U. }1 i/ ~- P' t8 L
  3.   uint16_t fftLen,9 F$ D, Q5 ~6 O3 ^0 V
  4.   uint8_t ifftFlag,8 A* o0 F7 i3 [$ m
  5.   uint8_t bitReverseFlag
    / q  H, P8 d- a& u
  6. );
复制代码
0 U5 G1 Q4 F6 G0 `
定义一个状态变量用来显示FFT的初始化是否成功。* ^, o2 s- J0 A# v, c
定义一个FFT的配置变量。+ F. }, r9 |# |2 D% h6 i! \
初始化FFT。
$ O% {0 G6 s, W, L
S:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。
; H( p% y% y8 q" ^" g+ E+ U0 C' I3 E- }3 c8 {7 a: H
fftLen:FFT 的长度。
: z7 S1 B2 m2 k7 `; H8 y2 g( x2 q) S
! a0 W! R/ K  S- J
ifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。
3 h' z1 w4 ^- }" m: Z0 n: m0 i2 j/ l  R6 @
bitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。- v* D# f5 x2 k/ i
% p4 N6 s3 C8 j4 M% A. g# d" ~0 R7 C
在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。/ B* W9 O. p$ ]" D
( t' D8 k3 u0 I' H
当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。0 H" s4 g  c# t+ y
) n, ~3 ^, z) O
在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。
' [' l4 `7 J: Q# {! o$ @' z+ y
举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:3 Q6 B  b% {* U( Q
) {- a8 N+ a' P8 r+ u* ^
0 1 2 3 4 5 6 70 V7 A+ @/ t3 L  G
  Y% b- O- E' S0 F' {5 j0 z
在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:
9 c* k$ m' W2 s' m% r% S
) F  v/ Q5 ]) U: f0 w3 D
0 4 2 6 1 5 3 7
; o" ?/ k8 ?" s. p3 @, w
' M$ w) E$ F# q5 K- T在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。
: E0 T* D/ H. U( Y& c# [7 s' j2 x& r5 ?: b6 y) B
进行FFT并转换为模值8 u. L  P# r, j6 A* A6 r  q6 E" E& R
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算
    1 w  m, T+ r3 _
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码

7 }0 y/ ?- c3 w8 _对输入数组进行FFT变换,并将FFT的结果转化为模值。6 b5 Q( `7 d. Q
) B) c1 h) ~' r
测试
% ]9 ]# F3 h6 X+ y- ~我们进行一个简单的测试0 t9 B0 P  L: C8 f3 ?5 ?* p. t
  1. #define FFT_SIZE 1024
    1 M* `& E  F5 ~3 R
  2. #define SAMPLE_RATE 1000
    0 G* A! ^! r$ n1 E# o( E  z
  3. #define NUM_SAMPLES 1000
    # X" H1 i0 n% H5 I* I4 t1 ]
  4. #define FREQ_OF_INTEREST 100- a7 O; [& H# [- q6 b
  5. for (int i = 0; i < NUM_SAMPLES; i++) {
    9 q' w& j- n+ ~
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;
    , F0 b* Q1 s/ P* o
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值% c+ g' h; R7 H. {; J  f) ]' k
  8.         inputSignal[i * 2] = sin_value; // 实部
    " A! s& K" [: b; K: A% D! ^% X5 L
  9.         inputSignal[i * 2 + 1] = 0; // 虚部
    & I0 i! D1 C9 S% x# u
  10.     }
复制代码
' |* N: ]7 g5 b) `" K1 m
一千个点的采样值,频率假设为100HZ作为输入信号。; D' R8 v' B2 A+ q2 z- B1 c
  1. for (int i = 0; i < FFT_SIZE; i++) {
    3 @) J. C) r( T" g" s  |+ ~
  2.         // 计算复数的模值
    0 I- n6 H8 Z/ B' F
  3.         float32_t real = inputSignal[2 * i];7 D; ~0 l7 [* S- |5 _4 W
  4.         float32_t imag = inputSignal[2 * i + 1];
    ; _. i# ?' `: h) q3 b
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);
    , p6 [- K0 A4 @, X- u9 g
  6.         
    4 i7 f0 `. {7 G+ P
  7.         // 打印每个频率分量的模值
    $ E0 z" s& d. {! M9 W  z
  8.         printf("Magnitude: %f\n", magnitude);# k/ w4 t0 J9 ]! P
  9.     }
复制代码

) \9 ?& O  S6 B1 h4 m! b9 W8 W进行傅里叶变换后打印模值。* B, P, E! G) l. k) ~) q! P
) `7 d$ e; L, g& _  E' |4 e
微信图片_20240529190744.png : f4 k+ y9 m$ m' X+ T  y* v
9 z( L. K1 b9 b. ?4 D
可以看到傅里叶变换执行成功。
/ ]0 P% h. E3 y' _
  1. for (int i = 0; i < NUM_SAMPLES; i++) {
    ( t6 l! g! u1 U- T2 C
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;" J$ p- ~$ s. |  l% }! w+ P
  3.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t)+sinf(2 * PI * FREQ_OF_INTEREST * t*2)+sinf(3*2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值% U% W) Z# Q' Q7 U
  4.         inputSignal[i * 2] = sin_value; // 实部
    : f+ R  `) z& Z; x, ]
  5.         inputSignal[i * 2 + 1] = 0; // 虚部2 H' `  i6 u' L. L; I* w1 D
  6.     }
复制代码

- h: l" c, Y+ H' l5 q1 e我们将信号制作成100HZ+200HZ+300HZ的信号。" m' ]: i7 \5 Z4 C2 x

6 b6 j3 N. P2 p7 I 微信图片_20240529190740.png
9 _+ ]/ N; p( z  @' ]# p) ^; x& j, M2 j1 j! n5 k  a* q. a- T
( l) u( {$ P& ]$ V8 ]/ Y0 G/ Q

. R. T% v! W$ o7 m转载自:电路小白  c5 M9 V' j/ I
如有侵权请联系删除
2 |3 J" s+ G" W1 F6 y% z# }
9 G& L4 d+ o) Y- `! I
1 收藏 1 评论1 发布时间:2024-5-29 19:08

举报

1个回答
STMWoodData 回答时间:2024-5-29 22:03:20

这个FFT不错,学习参考一下

所属标签

相似分享

官网相关资源

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