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

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

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

! Y* L: ]- q- |& e9 H* v 微信图片_20240529190800.png 6 H7 H6 F3 a0 B

8 |5 U9 R8 G/ {FFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:- m. ?* j7 I1 t" W2 q

8 u# j3 U# `3 Q9 b
微信图片_20240529190757.png
  x/ ~5 [- Y1 V7 e3 H& k$ E- Y1 y
3 v$ s  r, f8 f% w1 y其中,x(n) 是输入序列,X(k) 是输出的频域表示。
5 _8 m+ c* M. I- w) S* l) {0 W* G+ B
准备工作:1 I5 T( ?  B& y2 m2 |

* S" E5 v1 V$ M3 z* X

5 Y% w/ ^. P4 J* y 微信图片_20240529190754.png 4 O  S3 f: U9 b0 W

8 E+ ^& a9 z$ r' ~; B3 Q 微信图片_20240529190750.png
2 l& X2 F, i( M; E4 X: W5 t
* u& Q% B! W/ i- l$ n$ q
Keil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。: a+ `5 v7 m& [6 M/ {

5 ~: I6 I4 y) a6 }
因此我们需要在Keil中安装我们的DSP库。
- B6 W( z. h4 N. t5 ?2 h5 ?% R
  1. #include "arm_math.h" // 包含DSP库
复制代码
. d. [9 {5 Z; y  U: `, `1 x
首先包含我们的DSP库。
/ v0 M/ F' k9 N9 C6 \
% d8 M% W; Q6 v- b
/ i- q* @+ d7 R' l; X0 g; S
  1. #define FFT_LENGTH 100) A+ Q& v4 l/ W/ a3 G* |: H
  2. // 输入序列; x/ X" m8 e; z6 |8 L" v, ^
  3. float32_t inputSignal[FFT_LENGTH*2];
    ' E2 N5 K. |/ W8 v
  4. 2 O, s( S4 C) @) s: Y
  5. // 输出序列,存储变换后的结果
    1 k; D6 q1 M- p! s6 N/ i6 ]
  6. float32_t outputSignal[FFT_LENGTH];
复制代码
8 P5 a. C' x1 X9 Z5 I  e
定义FFT的的输入和输出数组还有数组长度
  P/ ?! p+ P8 [
  1. arm_status status;! W3 j9 d! W, k0 B6 }$ X
  2.     arm_cfft_radix4_instance_f32 fft_inst;
    ; q: g+ E4 d7 V( G
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32() T' ]! _7 [5 B# q0 U7 b
  2.   arm_cfft_radix4_instance_f32 * S,- H5 E/ ^5 Y+ H
  3.   uint16_t fftLen,
    3 D) ?# q6 B( j4 Z9 O. C# k
  4.   uint8_t ifftFlag,: C8 R2 z! V: X
  5.   uint8_t bitReverseFlag* h! [: n. F0 \& q( Z' O8 r. H
  6. );
复制代码
) A/ ]  ?9 \' X) F$ a
定义一个状态变量用来显示FFT的初始化是否成功。5 J6 H. S0 U& W* T- _
定义一个FFT的配置变量。$ i* b' [9 Q2 a+ l; c# I9 Z  y) S
初始化FFT。
& y2 J: _' }  O9 [7 @& T
S:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。
( W5 G9 n- F# M0 b2 e! A4 }5 x, p! x6 M1 @  w7 o0 M
fftLen:FFT 的长度。# v$ _, _2 x) C4 A: t

2 F8 R% c: j/ B, d' ]ifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。
) ~/ n8 ]0 ^7 O; C& g: ~% j
* V4 G% A# `9 h  K+ E5 A- r% \* P% VbitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。% N+ _4 |3 U3 t
1 h8 q1 r# V) w7 o
在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。
$ B( _4 c, e* k
  }2 |2 `; ~+ ~+ _0 B- N
当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。
9 v3 C% m& k0 D1 M2 a+ e

& C" [9 ~/ ~$ G/ B, Q, h在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。
) e- B0 O* F3 C$ y7 w+ g, A8 ]2 A. L- Y. M; y9 s' {
举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:* Y" m& c: U- t% D
# e. |, B* F/ O2 \3 z
0 1 2 3 4 5 6 7
2 R5 Z# M$ P( M9 J8 C# v

7 a- Z- u0 I3 t3 h在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:
3 X% j& h- R: z
0 L6 a, k; r, o! |0 V8 ~+ H
0 4 2 6 1 5 3 72 x7 ^. K% d" P- V1 t# `9 i

5 \; S% q( n, _4 _1 B1 R在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。; @1 s) G" q* p

5 T/ B- s5 f4 c进行FFT并转换为模值1 `: e6 a9 J9 N/ \( ~! X# K
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算
    7 |$ h# v! J! I
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码
% \/ ?& k8 w0 a* R: ^
对输入数组进行FFT变换,并将FFT的结果转化为模值。% V% Q  p1 ?- q) U5 x) R% `
( K& O' Q! p' p
测试
3 K& _, a( k5 G5 z9 X我们进行一个简单的测试
0 v2 i+ L/ c2 w9 g, N
  1. #define FFT_SIZE 1024: f! b9 A# M; }9 F( b
  2. #define SAMPLE_RATE 10005 P$ L6 @3 j7 N& k) R
  3. #define NUM_SAMPLES 1000- L, {4 b# a! I" ], x* V2 B
  4. #define FREQ_OF_INTEREST 100
    2 p2 F: R! O1 i, a$ ~, g6 C
  5. for (int i = 0; i < NUM_SAMPLES; i++) {( {8 X' S- n, C
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;
    % v$ P0 c) c$ |
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值% W! L# @/ Q" g+ e2 B8 F$ M! ?
  8.         inputSignal[i * 2] = sin_value; // 实部1 G: _( S% z  o) \5 h
  9.         inputSignal[i * 2 + 1] = 0; // 虚部  s- T$ G# ^# g" Z* p$ y5 |9 N/ v
  10.     }
复制代码

: i6 X' t! t4 H7 W9 h一千个点的采样值,频率假设为100HZ作为输入信号。3 I& o/ y0 A9 D; \6 x% i% h; `
  1. for (int i = 0; i < FFT_SIZE; i++) {1 H! r( E# d* F( r7 ?
  2.         // 计算复数的模值- M$ I' w( a. L6 O* ]. ~, D
  3.         float32_t real = inputSignal[2 * i];
    3 C  t. \9 C& l/ U
  4.         float32_t imag = inputSignal[2 * i + 1];
    . H1 ^7 {, L( f7 s4 P
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);3 S6 I5 ^9 M* R) c( y- O
  6.         
      o2 e( c- A8 u
  7.         // 打印每个频率分量的模值; X+ G1 k8 @. a! w1 P5 c4 K
  8.         printf("Magnitude: %f\n", magnitude);
    $ e7 c5 B6 ~& u. i8 h, G
  9.     }
复制代码
( _$ k) A' K1 v: u  x: ?* w2 ?
进行傅里叶变换后打印模值。
9 K# S" m7 Y/ ?- D7 T: ^2 @: M6 i/ G7 B0 k# _4 p( w2 @
微信图片_20240529190744.png
/ y/ H. O* Z8 h

. @% p! c& A  A可以看到傅里叶变换执行成功。! t# K0 ^) W* n7 `# E7 t
  1. for (int i = 0; i < NUM_SAMPLES; i++) {! z; [- ]- ~: L
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;
    ' h  K, |6 ~5 ]% N3 @/ ]% O7 y, A
  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); // 计算正弦波值# S: t7 O* w4 I
  4.         inputSignal[i * 2] = sin_value; // 实部
    2 d- o$ i) P" s& }5 ?
  5.         inputSignal[i * 2 + 1] = 0; // 虚部9 N% q: S. F- h2 m
  6.     }
复制代码
, b. Y) ~% m7 p9 v
我们将信号制作成100HZ+200HZ+300HZ的信号。
1 J/ D4 h( X) m. L' F4 s6 K, k8 B: v0 {6 O8 o/ G
微信图片_20240529190740.png   z5 ?) }0 G4 `" K& z2 M# M. U
- f9 D9 f* m+ H: E: O  K# \5 n
' E0 P( `8 x, f' E9 D7 n' m- p
6 i8 }' W  t( ]2 y
转载自:电路小白
/ c6 I4 K7 t" ?如有侵权请联系删除7 s( ]# F5 S3 h/ X! v

$ N1 B+ }2 _3 |( @1 j
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 手机版