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

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

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

# D5 W: \$ [" u, N& D) \0 w; F 微信图片_20240529190800.png
) o# h" F8 z- t! d0 q$ r9 h

: P. y8 D) G( W5 sFFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:
* }* r# }9 F: a; B4 z+ W( t4 s: q" l, k2 ]1 S' C: l5 ~
微信图片_20240529190757.png
' }' E% w& D+ F# C8 V
2 u% p  v8 m* r; S" q7 @其中,x(n) 是输入序列,X(k) 是输出的频域表示。( q2 `; u% n- B' q

/ U6 x4 [9 k. _& U$ P( A
准备工作:/ q1 c) i6 D( S
  q4 i' o; U3 l- L0 n+ N5 f

2 i' w. ^! F& R* z 微信图片_20240529190754.png % b* D5 j" M* I6 i; o" [* F+ _
# r7 S" G4 K; W  ~9 k  W
微信图片_20240529190750.png : W! @: }4 N, }

  z( O" m" h$ m( A6 `, qKeil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。
3 w0 X: x* S' B. m8 \# O& F* u9 S
因此我们需要在Keil中安装我们的DSP库。
/ \+ e" m- e$ D# |* [
  1. #include "arm_math.h" // 包含DSP库
复制代码
: d# B3 M! d# S* S& O
首先包含我们的DSP库。
2 `; J4 i5 v) e/ P

+ l/ Q! O/ A8 _' E
+ R% M6 Q. X5 O+ K' m
  1. #define FFT_LENGTH 100$ o) Z3 z8 I6 o8 w" g
  2. // 输入序列
    8 S' [: n! z/ b  R- e
  3. float32_t inputSignal[FFT_LENGTH*2];
    # q+ b7 A" e4 S+ x5 G1 l4 _9 N# e
  4. ! x2 m0 ]6 k: n$ [
  5. // 输出序列,存储变换后的结果
    - l6 l7 c5 K. S5 j8 s
  6. float32_t outputSignal[FFT_LENGTH];
复制代码

0 `. k9 l- p& b% L( f5 j2 J2 E3 T定义FFT的的输入和输出数组还有数组长度
4 m8 E( r: r" \# y" D2 |
  1. arm_status status;
    ( a/ p/ f2 L0 w1 Y
  2.     arm_cfft_radix4_instance_f32 fft_inst;6 x& F+ j  G$ K
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32(
    , a  x2 Y6 ]2 Y$ }/ w- w1 q
  2.   arm_cfft_radix4_instance_f32 * S,
    6 O. O: \1 Q- }# l$ l$ M% S
  3.   uint16_t fftLen,
    1 d- M: l  Z  k: G3 e, y# h
  4.   uint8_t ifftFlag,$ g( C: w6 }2 L, Z7 c% p) b
  5.   uint8_t bitReverseFlag
    . f' {7 ]3 i/ q. F" D. x& V, q: J
  6. );
复制代码
5 f% o9 i9 x# O4 `0 @) @  ~
定义一个状态变量用来显示FFT的初始化是否成功。4 y  b3 p' b% E# P6 u! ?  y8 v$ v
定义一个FFT的配置变量。
: i- }: Q9 u- b; [% U初始化FFT。
& Q" K2 b/ G6 ^$ B  {5 C
S:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。8 i* e7 E  T5 X/ s( {

& e% f2 z0 q4 f: p; U- jfftLen:FFT 的长度。
  w3 f% Z8 D4 P& O

2 W( H+ Y" z6 @, i; SifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。2 p# `- i, }: i! m
9 g9 f+ u# Y4 s/ R7 {5 C
bitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。
" u1 Y" [+ d5 H! P+ N# e+ w
: x5 x$ ^2 D1 g在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。
1 V/ p9 ~5 `  c* N$ D$ D+ ?
  F2 Z% Z3 t& ^- o
当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。5 {3 W; ~6 M6 }- K% `& r+ ?

8 u1 P5 I8 i' x- E/ m' e' U- w在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。
' _& y0 R* I$ G' P
0 y0 x1 g$ g% F, T- ]* s举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:
) e3 ]% U0 B( x. d7 b
7 t! y9 C  f! o7 ~* z; Y& N8 K6 k0 1 2 3 4 5 6 7
' V* e2 Z7 ~" E) \
) d* i  n+ O0 s' x
在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:
+ h) j2 R/ {0 y5 V* k. P% a

# S; s' |  d( {5 j0 4 2 6 1 5 3 7
& {5 V5 w( [( @+ f! J( W1 G5 A& o# P/ O
在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。
4 r1 E) C1 M& _3 @8 d( r9 A7 p8 {" j3 k% t
进行FFT并转换为模值
3 J( c. }# [# x$ ~3 g3 a2 \& w
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算6 M3 f. t: G* O6 {$ a
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码

# `$ u# s8 [7 `; e; J  B! `/ R对输入数组进行FFT变换,并将FFT的结果转化为模值。% L. [& j8 E1 ]  o1 L  i, T

- l$ R6 e7 w1 N8 O
测试2 Y! \  e6 m" k7 f+ u
我们进行一个简单的测试
! U7 Z, I4 R) Q4 H
  1. #define FFT_SIZE 1024: F+ v3 T  [# Y$ r, V4 U8 l! u
  2. #define SAMPLE_RATE 1000) W! s3 D: \# @' v
  3. #define NUM_SAMPLES 10000 Y+ E+ {+ E' A3 [* ]- |  Y
  4. #define FREQ_OF_INTEREST 100
    4 I  z& ^5 @' ]* h1 G8 ^3 J/ s) ^9 [
  5. for (int i = 0; i < NUM_SAMPLES; i++) {
    2 S- Q+ e& s. [! w, b0 f4 a9 [
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;3 N+ t( v, c1 L7 f2 b2 R' o
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值
    9 [, ]. B$ H. a+ [; M& B% K1 e
  8.         inputSignal[i * 2] = sin_value; // 实部
    * A/ q9 j$ o* ]* p
  9.         inputSignal[i * 2 + 1] = 0; // 虚部
    # f3 _" t% O! d
  10.     }
复制代码
' ]% i! E9 E+ P" J7 X
一千个点的采样值,频率假设为100HZ作为输入信号。' j' d! ~" a' G* r6 ^- _4 e3 }' P
  1. for (int i = 0; i < FFT_SIZE; i++) {0 }$ y# B2 f. T( i, L
  2.         // 计算复数的模值
    ' r0 l/ |' B: ]$ |
  3.         float32_t real = inputSignal[2 * i];
    5 o' a& f8 n2 M' D
  4.         float32_t imag = inputSignal[2 * i + 1];* V# i+ u& o4 C6 b: ]
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);9 e# B. H6 c# T
  6.         " V4 A2 i3 ?2 B. Q5 ^" v) d
  7.         // 打印每个频率分量的模值
    " X! y1 N% m% P& c8 S
  8.         printf("Magnitude: %f\n", magnitude);
    / r" w6 U+ ]! Z" A) E
  9.     }
复制代码
, e) I( g7 z/ f
进行傅里叶变换后打印模值。6 b. O: f/ y: ~2 K
& {6 F5 c9 D& U5 h
微信图片_20240529190744.png
; j2 b% y9 y) N
! ^& W  E" l- P
可以看到傅里叶变换执行成功。* Z& S! w* q( B8 Z* f
  1. for (int i = 0; i < NUM_SAMPLES; i++) {
      X. |2 T4 F8 ~$ |9 Q
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;2 L0 u! q' A- M* \2 {7 A6 N
  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 L. T! G0 Y  h' s% Q
  4.         inputSignal[i * 2] = sin_value; // 实部7 Q' W5 O9 P: l3 j* ]
  5.         inputSignal[i * 2 + 1] = 0; // 虚部
    / c# P3 N/ @: \" B
  6.     }
复制代码
* |6 v7 `% t# e
我们将信号制作成100HZ+200HZ+300HZ的信号。2 C8 {* M$ _6 z6 y8 K# W. w
- F, o5 A: {* P) w
微信图片_20240529190740.png : M- E+ l- t& v! U8 b* b4 F" b1 w
, T. c' K/ P- f, n: s% U( S

; D! X" h) ^7 h, J) D" F+ ^
3 L5 L) C- ^! k* A0 m& c( e6 i转载自:电路小白8 g+ q. L% s8 q5 p% x
如有侵权请联系删除
# u) E" M5 Q' e3 Q# s4 c+ ^: P. v+ S4 F; N) ~
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 手机版