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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:08
快速傅里叶变换(FFT)是一种数字信号处理中常用的技术,用于将快速序列转换为频域表示。在嵌入式系统中,如基于STM32的微控制器,实现FFT可以帮助解决信号处理的需求,例如声音处理、图像处理等。本文将介绍基于STM32的离散傅里叶变换的原理、实现方法和应用。
4 |$ G5 [& }! a1 `' }/ M, }( B) r2 a$ b' i  p8 W5 E9 S
微信图片_20240529190800.png , W4 W( y" i1 y6 t/ v  ~
( A1 j, y5 f' b3 H7 {5 _
FFT是一种将时域序列转换为频域表示的技术,它将一个序列的N个采样点映射到频域中N个频率分量。其数学表达式如下:" y9 @1 o7 r; h% f( v( }& b

, H. ~. {2 G: d9 s
微信图片_20240529190757.png 8 i0 p3 z2 }6 q5 T
9 ?) v3 j2 }) ^( J1 j$ N
其中,x(n) 是输入序列,X(k) 是输出的频域表示。
0 r2 N7 e/ r* E7 {  E9 a! d
( ~8 P! [. I0 q
准备工作:
2 V' e* e0 g. h- W( M4 U" A8 v1 `5 `+ m# i6 F
2 g2 U( q5 T, ]: ^, A9 F. J
微信图片_20240529190754.png & L$ d; P) ~) e2 F* i# `
5 I6 R  i0 v! ?* m' S" R
微信图片_20240529190750.png : I6 Y" q5 X2 }# b; j0 Z

. T0 ^; J( Z! R& kKeil中的DSP库(Digital Signal Processing Library,数字信号处理库)是针对ARM Cortex-M处理器系列的一组软件库,用于提供各种数字信号处理功能的支持。这些库提供了一系列优化过的算法,可以帮助开发人员在嵌入式系统中高效地实现音频处理、图像处理、通信系统等各种信号处理应用。
; M$ r- ~3 F( t+ q6 [. o
' K6 i# y+ v. z# H! p
因此我们需要在Keil中安装我们的DSP库。5 u$ `. H, K1 X  y) n
  1. #include "arm_math.h" // 包含DSP库
复制代码
' {/ O$ r+ e( ^" ]% @
首先包含我们的DSP库。
0 c9 B0 b& R! c+ k" C5 }; I6 n

# R) r* P% j6 \& Q, s" s( i
" ~" o9 j6 w; D9 L1 Q0 x* ]
  1. #define FFT_LENGTH 1005 {* k& ^1 |8 ^; b$ M$ D  k
  2. // 输入序列# ?9 _- S) i! j+ p: i
  3. float32_t inputSignal[FFT_LENGTH*2];4 n, Q5 d0 }$ a/ E0 L% P) Y; R

  4. 1 ~3 a/ F, C2 ^9 o& U
  5. // 输出序列,存储变换后的结果3 P+ E* T+ d! I* {8 ~" V+ A( h
  6. float32_t outputSignal[FFT_LENGTH];
复制代码

& p3 q2 D0 m, ~! `6 q3 V# ^5 R定义FFT的的输入和输出数组还有数组长度
: l+ O' d: Z* M' I6 O% r
  1. arm_status status;
    % I3 _+ c# V2 h/ F( _! m$ C" L
  2.     arm_cfft_radix4_instance_f32 fft_inst;: c1 O+ c7 N/ H$ X* t# g5 w4 X
  3.     status = arm_cfft_radix4_init_f32(&fft_inst, FFT_LENGTH,0,1);
复制代码
  1. void arm_cfft_radix4_init_f32(2 W: f" f: j9 ^. a
  2.   arm_cfft_radix4_instance_f32 * S,0 B% b, O+ h& L- r1 E  ^! ~# {
  3.   uint16_t fftLen,
    5 `0 A+ L2 k+ ~' U! b$ [% P) D
  4.   uint8_t ifftFlag,8 n) b% Q$ T* L: M0 E) k! E
  5.   uint8_t bitReverseFlag
    0 V4 k( F- M% c4 T% z3 g$ o" }
  6. );
复制代码
0 ~6 C0 X6 x( X/ n& t% t9 U
定义一个状态变量用来显示FFT的初始化是否成功。4 v! V3 X- _$ Z" p9 h( o
定义一个FFT的配置变量。
( N8 G: {. ^+ X# H, f: e6 s% L& M初始化FFT。
8 K9 I- J; s$ `1 b) \# n
S:指向 arm_cfft_radix4_instance_f32 结构体的指针,该结构体定义了 FFT 实例的状态信息。
9 U- p$ n2 T/ U% r; c6 y
. {! r" b* l4 KfftLen:FFT 的长度。
& F- v  q  m+ ^' \4 t" ?
* \, Z7 `: _; u: c" n4 ~& U+ l
ifftFlag:指定是否进行逆变换。如果为 1,则表示初始化的是逆变换的 FFT;如果为 0,则表示初始化的是正变换的 FFT。( y7 N: L. C9 G2 _6 Q" M0 S8 y) P
' w. [; ?5 [' s2 {4 u; G; v0 F7 _- i
bitReverseFlag:指定是否进行比特翻转。如果为 1,则表示进行比特翻转;如果为 0,则表示不进行比特翻转。0 H! S& D* a9 H! s" J

0 \3 m5 A! U! ?+ b* g在FFT算法中,比特(bit)反转是一种关键的步骤,用于将输入数据重新排列为正确的顺序,以便在后续的计算中进行有效处理。7 B2 S% C1 p; g) q9 U
+ s0 y( v+ ~) h
当进行快速傅立叶变换时,算法要求输入数据的顺序是按照特定的方式排列的。特别是在使用基于分治法的算法(如Cooley-Tukey算法)时,输入数据的顺序必须满足按照一定规律的排列。; K% X- w$ Q5 F9 @
. A) [6 O: b& g1 T4 z
在实际的FFT实现中,最常见的方式是通过比特反转来重新排列输入数据。比特反转就是将输入数据的比特位(二进制位)的顺序进行颠倒。这是因为在FFT算法中,数据会被分组,并按照一定规则进行反转,以便在每个阶段的运算中,数据可以正确地与其它组合进行配对。, t# _( n; ], J& {1 G: E! h

9 F/ f) G$ _$ H2 w2 y9 n举个简单的例子,假设有一个长度为8的数据序列,按照0到7的顺序排列:
" s1 c$ f! h- n4 P/ {1 ~9 B& e
& k" s9 i" s  o& x+ M, j# D0 1 2 3 4 5 6 7
7 G- Z6 X1 A0 u0 W- d! r$ G! [7 G

1 H( D- B" t( S) n在进行FFT时,需要按照一定规则重新排列这些数据。比特反转操作将会对这个数据序列进行如下的重新排列:4 ?- g( g  }" u" L! y
6 p4 B# I0 V  ]! b5 ~
0 4 2 6 1 5 3 7
$ E+ }4 H7 \) Y. }, Y* g8 U. n/ P$ f0 U
在FFT算法的每个阶段中,这种重新排列都会使得数据正确地与其它组合进行配对,从而实现快速傅立叶变换的计算。
1 x+ h5 _- O. c8 P3 \: e
: i5 g3 t4 K2 w) l! Z4 s% {% ^进行FFT并转换为模值
$ U; c. L" j7 P' N3 X- B
  1. arm_cfft_radix4_f32(&fft_inst,inputSignal);          //FFT计算
    ; ?  @+ G# D, ~1 R# p# G+ x
  2.     arm_cmplx_mag_f32(inputSignal,outputSignal,FFT_LENGTH);  //取模得幅值
复制代码
) `# |$ z( \3 R+ U' E9 p
对输入数组进行FFT变换,并将FFT的结果转化为模值。$ j3 K& F+ f5 }% S  Q
4 |+ s+ y4 h) Z. {7 p4 P
测试. ?. q; ^0 W, m% m6 ?0 H
我们进行一个简单的测试: N9 ^9 @" z8 ~! ?  |" T
  1. #define FFT_SIZE 1024) M5 Y5 s' N/ q7 ]! U- u$ ]+ i
  2. #define SAMPLE_RATE 1000
    - t' H: i+ Y4 d% y: X/ f  N6 j
  3. #define NUM_SAMPLES 1000  W3 b6 X4 @6 S9 t8 I# b
  4. #define FREQ_OF_INTEREST 100
    ' F3 q2 ^0 h% K5 j& X2 g
  5. for (int i = 0; i < NUM_SAMPLES; i++) {
    : g$ _6 b* l/ J) ?. G. r& K
  6.         float32_t t = (float32_t)i / SAMPLE_RATE;6 P4 N( _2 G" h1 m  d
  7.         float32_t sin_value = sinf(2 * PI * FREQ_OF_INTEREST * t); // 计算正弦波值
    - w4 M; ^- S7 |& a, W7 @
  8.         inputSignal[i * 2] = sin_value; // 实部
    + |$ I& d$ B) Q; [5 n
  9.         inputSignal[i * 2 + 1] = 0; // 虚部5 G) B: Z9 E, `" _, i& v
  10.     }
复制代码
: U9 J$ u& L, |4 S
一千个点的采样值,频率假设为100HZ作为输入信号。
- m- E" f, @  c4 |& I( B
  1. for (int i = 0; i < FFT_SIZE; i++) {+ P" x& f$ `3 E+ F
  2.         // 计算复数的模值
    , {- ~% @$ ?+ u. o# ]: G
  3.         float32_t real = inputSignal[2 * i];
    1 w( O6 t' m  b8 [9 i
  4.         float32_t imag = inputSignal[2 * i + 1];8 p9 x" j4 A2 S
  5.         float32_t magnitude = sqrtf(real * real + imag * imag);& v/ E( O  J# j& U+ ~) G8 k
  6.         " m. z/ b# f6 t+ I
  7.         // 打印每个频率分量的模值6 b  S9 G2 z8 @7 T% k0 [
  8.         printf("Magnitude: %f\n", magnitude);
    2 g$ d; U' O3 G# y3 ?# u1 ?
  9.     }
复制代码
3 \+ ^+ U3 t; G& I. Y
进行傅里叶变换后打印模值。
0 S" o$ O$ Y! f
2 [" c' o' a( @5 u& M 微信图片_20240529190744.png 3 {) P& x! i% p% l+ I  y) |* A
6 i0 R# w. {. t' W  k& x+ q3 Z
可以看到傅里叶变换执行成功。0 y2 k! J1 [8 U& o4 }
  1. for (int i = 0; i < NUM_SAMPLES; i++) {+ n. N" d' g- Y  G
  2.         float32_t t = (float32_t)i / SAMPLE_RATE;
    / ^& O# S+ Q2 \' o8 R5 E* {+ ?! h
  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); // 计算正弦波值; a' K- O1 T, r4 k$ ?* p
  4.         inputSignal[i * 2] = sin_value; // 实部
    * p4 g  z( y0 H7 f+ S
  5.         inputSignal[i * 2 + 1] = 0; // 虚部
    ! [: s. ^% u' J- {! d
  6.     }
复制代码
& @# }0 _* y: l2 D# \; _
我们将信号制作成100HZ+200HZ+300HZ的信号。
) a1 S; f4 _1 o' w" v* R: e! c# r- V6 U
微信图片_20240529190740.png
% E4 B" A) F& |: k
) e, }# J) [8 `& ^2 t/ a; H; v% _" C
3 \) `3 g" Z; P
+ W% o6 \/ e$ u转载自:电路小白
  l8 k1 ^6 h1 Z. {' A, [) m如有侵权请联系删除
$ ?/ ?  Z0 p! [1 Y$ d( @0 V  G6 k9 q. Z8 T
赞 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 手机版