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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:08
快速傅里叶变换(FFT)是一种数字信号处理中常用的技术,用于将快速序列转换为频域表示。在嵌入式系统中,如基于STM32的微控制器,实现FFT可以帮助解决信号处理的需求,例如声音处理、图像处理等。本文将介绍基于STM32的离散傅里叶变换的原理、实现方法和应用。/ ^0 g. w% s1 v! q

* T8 `7 g  M! P% e 微信图片_20240529190800.png
# L# N& m, O  r1 }3 G2 m" }
  [% [; l4 e1 Q5 P8 Q" K" c
FFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:& W+ M- c; [& T
# c# _5 H, @: L, q+ a
微信图片_20240529190757.png 5 Y1 q. ~3 B& x( |' u

; T  g5 Z6 X0 i; I! }  `% s' B其中,x(n) 是输入序列,X(k) 是输出的频域表示。
, U% q: l5 z9 W  J5 @7 u" C4 J
. H& W" Z9 D& o' j$ L6 F3 J3 B
准备工作:
. q( b/ R3 T7 d, b3 G* O% o0 O- [; R, \5 Q6 t  i& O
) v; m2 K( t( O/ g2 d- X2 Y
微信图片_20240529190754.png ; G2 h( U, T; u: @5 S* C
5 _/ B' Q0 w% [" P$ L2 A# C
微信图片_20240529190750.png " ^, x# k9 ~$ A7 u' l* N' h

9 ~" t" u: f' _. b: N1 _( F  a( gKeil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。3 l; @& k. [+ t+ l. k
: @+ y% \4 B' ]6 ], B/ A- s
因此我们需要在Keil中安装我们的DSP库。! j' G) a" d! G. v: M
  1. #include "arm_math.h" // 包含DSP库
复制代码
! \7 q7 p3 T  [5 D
首先包含我们的DSP库。

2 z0 b8 b; `- L& ~  W; |! [# X4 W% `3 Z1 J! X1 U, F& C% W

* w$ A% T" `9 Y  C( u3 j  E  |
  1. #define FFT_LENGTH 1004 G" m0 W- J2 ^- X7 C
  2. // 输入序列% }0 V# R- t8 W* {3 D1 S
  3. float32_t inputSignal[FFT_LENGTH*2];
    3 U. C: {/ {* f- r9 q

  4. , o) B+ t* J5 l
  5. // 输出序列,存储变换后的结果
    / r4 [- s. r5 s7 p6 @* ^9 _
  6. float32_t outputSignal[FFT_LENGTH];
复制代码
2 `: w0 I( m+ h/ N
定义FFT的的输入和输出数组还有数组长度% N8 \# W, C' X5 ]' {- e- N
  1. arm_status status;- H* q& B5 r+ q" S# L6 L
  2.     arm_cfft_radix4_instance_f32 fft_inst;" |. U3 L; f3 ], m! o! l  y
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32(: e; m2 Z! {) N) A  J
  2.   arm_cfft_radix4_instance_f32 * S,0 K* C% ~( f! w3 F5 G  r
  3.   uint16_t fftLen,
    6 W5 U. ^' U% Q0 d# a
  4.   uint8_t ifftFlag,
      \1 {, n5 |/ |- s2 S
  5.   uint8_t bitReverseFlag
    - `8 V+ X  ]# V
  6. );
复制代码

' r) _, F+ ?8 j5 w/ s! F; {定义一个状态变量用来显示FFT的初始化是否成功。% C; S. G; F+ G+ g- X" E0 c
定义一个FFT的配置变量。
1 ]* t4 t; V4 V3 v6 E初始化FFT。

0 V1 ]* w% [. w" ?9 F8 qS:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。
) s1 A9 B. v6 }
4 z" f5 |! j* {$ T9 E) J9 y8 HfftLen:FFT 的长度。* v7 \6 c+ T  s7 L6 Z/ ^' u
5 W8 {. J' e/ Q3 ]7 B* M3 U
ifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。1 o: Y6 _8 p2 P
% A8 @" t! N2 B+ z* J5 w4 }
bitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。
0 \- b" {( t9 Y. C1 u+ {  a( }1 A; u3 z
在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。
/ W) @* r6 s8 X4 F0 p- n

  k2 `# n0 Q* }  K/ W; H. l1 P0 }当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。
; n4 H, N- V: v% b$ \. T7 [4 U
! l' P) N; m) Z8 w* d+ g1 @
在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。
+ j) x5 Q) w+ d& Y+ c* ^% Y1 Z# H" n
举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:
# Z" H/ X# z8 b9 ?5 x' R' D0 d* u8 F3 y! ?! |) T* j5 R9 D( T
0 1 2 3 4 5 6 7: L7 y5 ]4 a7 Q9 B) m0 y% D: R

  U! {6 E' w; p' ~; f+ ~在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:
9 L- R2 V4 U& e1 {! C5 M
& H/ V) o! b5 c+ z4 h% ^. \" E4 m# c
0 4 2 6 1 5 3 7
  p/ Y4 K, G8 c! m  O& `2 w2 N/ H9 L( _
在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。/ ]1 ~" n* s' S* O

, d% h7 V* Y% [& g' ^进行FFT并转换为模值
* T; n( P2 Y1 c4 a0 s7 ]% v
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算
    9 z$ S2 O. l* W2 D& [
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码

& P; R+ {) @) ^% D2 q2 |对输入数组进行FFT变换,并将FFT的结果转化为模值。; }( N2 N3 G* L. C. W+ v2 g

' ^- G; Q, I4 {5 b) a# x
测试
4 d& }7 }8 F( J5 R5 w0 T我们进行一个简单的测试
( T7 h, d: d: O- F7 |
  1. #define FFT_SIZE 1024! }. x3 c/ X+ K; N
  2. #define SAMPLE_RATE 1000
    5 E. Y7 _* w# q2 C
  3. #define NUM_SAMPLES 10007 z1 p- }( L& t6 u- @
  4. #define FREQ_OF_INTEREST 100/ }4 K) i0 R' q
  5. for (int i = 0; i < NUM_SAMPLES; i++) {
    0 x1 a, r7 _. _6 V! G
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;, W  ~. \6 D8 E9 C7 i
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值
    * P4 v" T* t$ }* T. z& Q
  8.         inputSignal[i * 2] = sin_value; // 实部
    ( Q- F% }* t3 |/ i' v- v
  9.         inputSignal[i * 2 + 1] = 0; // 虚部( [0 O, ~. ^) E- L% z: Q
  10.     }
复制代码

! p7 Q9 s9 N5 W2 A  ]! r& |一千个点的采样值,频率假设为100HZ作为输入信号。: z/ F+ [; U0 J  g5 j0 d& K! ?
  1. for (int i = 0; i < FFT_SIZE; i++) {' i8 |+ k7 ^4 S4 R) \
  2.         // 计算复数的模值! L  B+ [: T/ y9 @! u" a
  3.         float32_t real = inputSignal[2 * i];
      W& B, U/ H" F+ I
  4.         float32_t imag = inputSignal[2 * i + 1];
      b" q6 I# l7 k' j, C3 k' T
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);
    - T! _3 a  D8 U! u! n
  6.         & }" H! G4 s9 p$ P
  7.         // 打印每个频率分量的模值
    % \6 T7 g1 i; }7 G3 J# X% k
  8.         printf("Magnitude: %f\n", magnitude);" Q# S, S2 W- S8 V1 y0 o
  9.     }
复制代码
- Q3 Y0 s0 X9 L1 ~: i/ y
进行傅里叶变换后打印模值。
% T$ y: Q9 s1 Y1 x% M
) a8 J2 v/ U: v 微信图片_20240529190744.png 0 M4 ~7 s( U6 y- _2 n5 i

" W7 E" k, O, ]3 H+ [+ z可以看到傅里叶变换执行成功。
7 x9 b8 w, g8 |& Q# ]& q2 z
  1. for (int i = 0; i < NUM_SAMPLES; i++) {, g4 c7 z8 Y  V7 e  n
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;
    % O' w: ]( L! l( \5 D; [
  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); // 计算正弦波值/ l6 N1 S5 D+ c1 ]$ Y; S8 _
  4.         inputSignal[i * 2] = sin_value; // 实部7 h/ g. Q/ @# P+ O
  5.         inputSignal[i * 2 + 1] = 0; // 虚部/ n8 j+ V, ~6 J9 D
  6.     }
复制代码
( q" P* `9 a2 q  V' k" p9 I- B& Z
我们将信号制作成100HZ+200HZ+300HZ的信号。
, w& K- D" F) m
( e! k! f  [$ n9 c# D5 t 微信图片_20240529190740.png : A) e6 e% a3 c) g/ D- }* t
8 m* v1 _2 o% O; C
- M5 J& q1 i# N

2 ?* T' ~1 \  P0 Q' z转载自:电路小白( y0 K; o2 M) I) X5 U
如有侵权请联系删除
- v8 f# F5 w8 d( l! R% w, ]# O
8 y2 a0 q- \6 D: v
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 手机版