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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:08
快速傅里叶变换(FFT)是一种数字信号处理中常用的技术,用于将快速序列转换为频域表示。在嵌入式系统中,如基于STM32的微控制器,实现FFT可以帮助解决信号处理的需求,例如声音处理、图像处理等。本文将介绍基于STM32的离散傅里叶变换的原理、实现方法和应用。
2 _  a9 |' r) \9 z
4 E$ F: D6 ~- \$ T; U/ o- ]  l" o 微信图片_20240529190800.png
. c1 S8 K9 ]/ e
- ~. x- `0 p! n$ e' l
FFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:7 L) z; ^$ g3 r
# v' {  W( I; ~# m  Y) ?; c$ H
微信图片_20240529190757.png + V6 y; X. f4 K* S; O
/ u& R: h- U/ U3 J# s8 b. q
其中,x(n) 是输入序列,X(k) 是输出的频域表示。/ j" B+ X# |  F8 x: x% J
; u9 }; g6 q* i$ ~. O
准备工作:
; W+ r5 M8 z" ~2 C( I, P- b: h' e+ }) U

4 k- ~  {6 D8 \/ ?5 H! T 微信图片_20240529190754.png & G$ d$ z8 E- s% b' ~
# O) @4 E% ~- z; ~5 y) ^
微信图片_20240529190750.png
) u) y+ x3 b; c" r
) L6 n0 {8 d- @2 G' Z/ p
Keil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。- D) V9 U# M/ X% @' J

$ [4 M" E" u3 N* T! }. N0 X. m
因此我们需要在Keil中安装我们的DSP库。4 F. N9 b, m, Z% p
  1. #include "arm_math.h" // 包含DSP库
复制代码

! w# K: |. T( f3 {" g首先包含我们的DSP库。
4 J: x9 d0 F+ p: Q, |
. T* }( e( R% H- S+ B* y8 g
: U$ z) L- F9 X0 ^0 _% v( V
  1. #define FFT_LENGTH 100
    " C: J6 p) N! ?
  2. // 输入序列+ Z7 s- t' v  }! x+ w; U3 b
  3. float32_t inputSignal[FFT_LENGTH*2];
    3 ?8 i& @6 {% N3 i( _" D

  4. , R# \& O6 H- [/ I0 R& P
  5. // 输出序列,存储变换后的结果* F6 H6 m3 c# ?
  6. float32_t outputSignal[FFT_LENGTH];
复制代码
  n1 ~* h. T2 _9 H" G
定义FFT的的输入和输出数组还有数组长度/ Y/ p- `1 [' v8 s; e( }
  1. arm_status status;
    6 H: m  S$ x# q5 q# l0 ]2 n/ k9 G0 V
  2.     arm_cfft_radix4_instance_f32 fft_inst;
    ; R' i( e* b' J) o1 B
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32(/ e6 @1 K9 k% `- V
  2.   arm_cfft_radix4_instance_f32 * S,
    0 _+ a, F4 j& P1 r# p
  3.   uint16_t fftLen,
    # a; a2 T* ^- H: `! A* Y
  4.   uint8_t ifftFlag,
    ( F8 F' {3 w( ]. s3 e4 I/ _5 F
  5.   uint8_t bitReverseFlag$ Z- L7 P/ U3 g8 a, _6 e2 O
  6. );
复制代码

/ E  g  B- ]3 ~$ I% r& E. U定义一个状态变量用来显示FFT的初始化是否成功。
8 o. c4 E% V2 H4 O0 g0 U& c* m9 I定义一个FFT的配置变量。' M9 }4 q: I! I3 D
初始化FFT。

0 ^8 R0 N6 C" @4 X9 p  p" p6 HS:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。1 I/ F* v4 ~, f0 C7 l6 S' \
6 U# O; S3 c2 e- e% a
fftLen:FFT 的长度。# r' x2 X6 ~; @- \. Z( o
( ?( D: n/ L' h/ k) F
ifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。# x/ `0 q* k! y; d; {+ z

$ g& A" x& T. ^4 D. [. w* LbitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。; I. x. ^# A9 \+ E$ L! J: f
% Y! U! e/ f7 x: B7 O& Y
在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。
3 H" S" _% l* h
9 a* a; u" l- g* l1 }& [
当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。4 d0 \  H0 o; a; f# C. L$ V$ H

. ~5 R. G* O0 n) @/ I9 {, |/ t在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。9 a5 {; T* V" f* h
9 `, E# B4 N/ X. S0 s. a% x/ D
举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:! }6 m& |; b) a- I

' ^' u$ ^* M' Y+ z. w5 r  \/ `0 1 2 3 4 5 6 7
, F4 D. U% C$ C" t6 r, G0 l0 V

  T5 h/ B0 j) k" m- c8 a4 Z9 G9 v在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:
3 `# g  }$ O) x" y- B
6 c4 u; f" M( U" f
0 4 2 6 1 5 3 7' C: S' O5 X2 ?. Z0 Z

+ u$ e$ r) c7 A$ y在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。
' S2 n2 |! i+ x/ ?( [! |' U% r7 m; N3 }, F: J. Q2 ?
进行FFT并转换为模值+ i2 n% x' M: q1 s; ?6 v4 d
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算% z1 F4 h( S  o" y7 _
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码
7 Z/ D/ h1 h5 [8 `9 T! V- L$ O& }
对输入数组进行FFT变换,并将FFT的结果转化为模值。
$ c% _3 W) i! R2 r4 j$ F+ e1 T0 P* E9 p# x  P( R# {
测试
  u' K" h1 K7 @1 Q# L) q我们进行一个简单的测试
0 R, `# H7 T( c& e
  1. #define FFT_SIZE 10243 \' I4 }& V: g; Y, }( z
  2. #define SAMPLE_RATE 1000/ x1 _/ B$ @# V; X2 p, i
  3. #define NUM_SAMPLES 1000
    / T4 R0 P2 T# Y# F# s2 U. j
  4. #define FREQ_OF_INTEREST 1007 L. J6 ]6 T: J. ^8 [5 z1 V8 J
  5. for (int i = 0; i < NUM_SAMPLES; i++) {0 F6 J, ^) {* n' ]4 @3 q6 |
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;
    " Z- U) j: n: N: ^7 v  h
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值
    1 q" d6 Z* }! w2 t) j7 |
  8.         inputSignal[i * 2] = sin_value; // 实部
    7 ]5 l& o7 a1 v* ]! c
  9.         inputSignal[i * 2 + 1] = 0; // 虚部% J- b' A* F# O1 g( F
  10.     }
复制代码
% \& e! m2 G, l0 W+ ]% i0 h# r& P
一千个点的采样值,频率假设为100HZ作为输入信号。! ^/ Y  P' D( X# R! S+ E
  1. for (int i = 0; i < FFT_SIZE; i++) {7 l0 I) L5 g- D8 N/ k* V- s
  2.         // 计算复数的模值4 V3 X7 S. D/ V+ t9 Y# d. y
  3.         float32_t real = inputSignal[2 * i];. m  U! Q) o5 g: K  k
  4.         float32_t imag = inputSignal[2 * i + 1];. {! G& O) {1 T5 e
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);+ B3 s* E4 t! J+ x( _( h& Y8 T) c
  6.         
    . |7 z" v, x( _; t7 Y' t/ t+ z
  7.         // 打印每个频率分量的模值. M' E$ o9 X' Y, }* Z
  8.         printf("Magnitude: %f\n", magnitude);
    . ^" D9 W9 w& L; j" p  c: ?. s( c
  9.     }
复制代码
# [! Z: O. y2 H3 _/ E  G$ }
进行傅里叶变换后打印模值。: B8 ?7 m8 H) ^+ k+ b, \; y
5 _- o9 ~* ^. ?+ t3 x- i
微信图片_20240529190744.png
) O# ^2 C8 I! E

* o! W& u# Y& Y$ H  c. e% r$ P! w可以看到傅里叶变换执行成功。- B6 y. ~* K! d( p
  1. for (int i = 0; i < NUM_SAMPLES; i++) {
    - x* {3 S4 R1 \* F6 Z
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;
    & K/ j. q1 p8 B2 D$ i! ?- M
  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); // 计算正弦波值5 [4 |: a* y( ?" j( E- A
  4.         inputSignal[i * 2] = sin_value; // 实部
    " Q! E6 P8 ^4 [, v
  5.         inputSignal[i * 2 + 1] = 0; // 虚部& \  K4 D5 \: W0 p
  6.     }
复制代码
% u# f5 X. s% W, m; F
我们将信号制作成100HZ+200HZ+300HZ的信号。
/ }( Y5 g, p" X: G9 j4 s0 P& R) V! A
微信图片_20240529190740.png
) i) L! l9 t7 O1 R8 i
" T4 I$ {* N) d( }: W; @: h2 h. B8 w, [; Z7 C7 y: S2 |
2 F/ ?1 B8 G$ D
转载自:电路小白
1 {' c$ X  t, x7 l9 d& @$ \8 q& ~如有侵权请联系删除& C; I, _! Z! L% @7 Q

. N2 h! r! l& Y' t+ m1 V
赞 1 收藏 2 评论1 发布时间:2024-5-29 19:08

举报

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

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

所属标签

相似技术帖

官网相关资源

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