前些日子,因为需要在STM32F103系列处理器上,对采集的音频信号进行FFT,所以花了一些时间来研究如何高效并精确的在STM32F103系列处理器上实现FFT。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用STM32提供的DSP库这种方法。 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 $ |+ K9 u, h9 e; |- C R4 @
1.FFT运算效率 使用STM32官方提供的DSP库进行FFT,虽然在使用上有些不灵活(因为它是基4的FFT,所以FFT的点数必须是4^n),但其执行效率确实非常高效,看图1所示的FFT运算效率测试数据便可见一斑。该数据来自STM32 DSP库使用文档。 图1 FFT运算效率测试数据 由图1可见,在STM32F10x系列处理器上,如果使用72M的系统主频,进行64点的FFT运算,仅仅需要0.078ms而已。如果是进行1024点的FFT运算,也才需要2.138ms。 9 @+ L$ L2 \0 p. G8 F* o1 B
2.如何使用STM32提供的DSP库函数 2.1下载STM32的DSP库 2.2添加DSP库到自己的工程项目中 下载得到STM32的DSP库之后,就可以将其添加到自己的工程项目中了。 其中,inc文件夹下的stm32_dsp.h和table_fft.h两个文件是必须添加的。stm32_dsp.h是STM32的DSP库的头文件。 src文件夹下的文件可以有选择的添加(用到那个添加那个即可)。因为我只用到了256点的FFT,所以这里我只添加了cr4_fft_256_stm32.s文件。添加完成后的项目框架如图2所示。 图2 项目框架 2.3模拟采样数据 根据采样定理,采样频率必须是被采样信号最高频率的2倍。这里,我要采集的是音频信号,音频信号的频率范围是20Hz到20KHz,所以我使用的采用频率是44800Hz。那么在进行256点FFT时,将得到44800Hz / 256 = 175Hz的频率分辨率。 为了验证FFT运算结果的正确性,这里我模拟了一组采样数据,并将该采样数据存放到了long类型的lBufInArray数组中,且该数组中每个元素的高16位存储采样数据的实部,低16位存储采样数据的虚部(总是为0)。 为什么要这样做呢?是因为后面要调用STM32的DSP库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: - /******************************************************************
% R# w I2 M* w6 {) i- J - 函数名称:InitBufInArray()
) M! `' b) N' D - 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)
% E) |& l% M- Z4 V6 w - 参数说明:( p" ?8 {/ v& i+ Y2 ^! E
- 备 注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部,6 Q2 K& b R! U8 I% Y- E
- 低16位存储采样数据的虚部(总是为0)2 h H/ C' x7 M$ U
- 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
+ @& M& x \6 E* s! J - *******************************************************************/
" h$ q5 n6 ~5 q; k& P1 ^% S8 z - void InitBufInArray()
- j- ^% s% a1 N - {
' M+ _* G) U( y - unsigned short i;4 T9 N& Y; o2 q5 ?
- float fx;/ z4 c! w8 L7 t; a
- for(i=0; i<NPT; i++)
& B' Z' l. h9 M0 u7 f6 b - {6 u* L3 ~: U j/ n* p: w$ Y
- fx = 1500 * sin(PI2 * i * 350.0 / Fs) +
6 F6 r0 C& F" q Z - 2700 * sin(PI2 * i * 8400.0 / Fs) +' ]8 s6 f3 P+ [7 {: [3 I
- 4000 * sin(PI2 * i * 18725.0 / Fs);
) q: @- n- E" \ m - lBufInArray[i] = ((signed short)fx) << 16;
2 R* r" H9 b4 v# L6 h/ u6 p - }
, \( m; |7 a" L6 T6 y% P - }
复制代码
$ C: z; n. W( U N 其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。
4 S% h+ h4 e* X& R
2.4调用DSP库函数进行FFT 进行256点的FFT,只需要调用STM32 DSP库函数中的cr4_fft_256_stm32()函数即可。该函数的原型为: void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); 其中,参数pssOUT表示FFT输出数组指针,参数pssIN表示要进行FFT运算的输入数组指针,参数Nbin表示了点数。至于该函数的具体实现,因为是用汇编语言编写的,我也不懂,这里就不妄谈了。 下面是具体的调用实例: cr4_fft_256_stm32(lBufOutArray, lBufInArray, NPT); 其中,参数lBufOutArray同样是一个long类型的数组,参数lBufInArray就是存放模拟采样数据的采样数组,NPT为采样点数256。 调用该函数之后,在lBufOutArray数组中就存放了进行FFT运算之后的结果数据。该数组中每个元素的数据格式为;高16位存储虚部,低16位存储实部。
, [3 B8 [ ]3 U" o5 \$ ]
2.5计算各次谐波幅值 得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。 下面是具体的实现代码: - /******************************************************************
' x" {, H! U3 [% H& n) \% o - 函数名称:GetPowerMag()( _9 [2 Q' O- C
- 函数功能:计算各次谐波幅值! |; h; V$ Y4 S" Z
- 参数说明:
7 g6 e! }; k. b1 k: K - 备 注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y)$ E* { m+ _' @7 L
- 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/): E$ x. V. ]; Q" `) |/ a# j6 w
- *******************************************************************/) x! s" r1 I+ R) f* ]
- void GetPowerMag()$ t( B* U2 v. W3 K; \% g" l/ l* P
- {' N5 \- F# n. F
- signed short lX,lY;/ D7 n( v# j0 E6 `
- float X,Y,Mag;
9 e- f! G/ G4 k% K - unsigned short i;
7 m8 ^, _0 ^+ e. _! @/ L - for(i=0; i<NPT/2; i++)) g% y+ t1 M) ]$ n. o
- {1 @1 Y, m, t5 w, _# {! @
- lX = (lBufOutArray[i] << 16) >> 16;
' o7 i2 X2 @1 l$ c - lY = (lBufOutArray[i] >> 16);
3 x `# ~3 W/ J! F4 {3 O6 s - X = NPT * ((float)lX) / 32768;- [4 N" Q5 v) N: W7 G8 z7 P% s ?/ F
- Y = NPT * ((float)lY) / 32768;% |9 a! T1 L$ |1 m/ G2 d
- Mag = sqrt(X * X + Y * Y) / NPT;3 _& C2 u' l2 x v
- if(i == 0)9 O" u) r! K. Q& ^. B
- lBufMagArray[i] = (unsigned long)(Mag * 32768);
& k, i+ z% _8 ^3 X7 d - else
; r7 d9 G* w' o: c - lBufMagArray[i] = (unsigned long)(Mag * 65536);
+ u) ?( S6 ]. X3 X6 g - }% l, d( R5 U2 B# K! V
- }
复制代码 Q3 V) y" T% B! P/ E
其中,数组lBufMagArray存储了各次谐波的幅值。 2.6实验结果 通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示: - i, P, Mag, X, Y
& K- a2 o1 N% N$ {) m# E* I - 0, 0, 4, 0, -44 G. g) c' ? M! e) }1 H1 h
- 1, 175, 14, -6, -4
* |1 j! H% j- H8 [$ E - 2, 350, 1492, 746, -3
& T3 O7 i4 M8 I* O - 3, 525, 11, -5, -33 i4 c+ y9 Z2 n; u
- 4, 700, 8, -3, -3
7 F$ d( S8 W( o; E8 O X - 5, 875, 8, -4, -23 E) [4 S& e! r* B! e, T5 i
- 6, 1050, 6, -3, 0
w5 W. o: m4 l* m7 P5 c; V- C - 7, 1225, 6, -3, 0+ D. s i6 q) j6 F7 f# w$ t
- 8, 1400, 8, -4, -2
' y( Y2 x- r* P. v; h - 9, 1575, 8, -4, 0 D t: t% Y0 |
- 10, 1750, 4, -2, 0& V' s- B. u# `( ]/ M) `5 P
- 11, 1925, 8, -4, -1
" ?; y; i! b) V8 S1 Y( h - 12, 2100, 6, -3, 0! z( {: s1 c, Y# _& h! q% Y
- 13, 2275, 5, -2, -2$ j* C# |6 n! y$ Q, k
- 14, 2450, 6, -3, -11 p$ [6 _/ O, p9 ]9 W
- 15, 2625, 8, -3, -3* _$ W, L# n$ |
- 16, 2800, 4, -2, 0
$ A2 I- A/ _, e, O( O# u# Y - 17, 2975, 6, -3, -16 @) M* y n5 A& b0 k& N
- 18, 3150, 6, -3, 0$ C$ W, q& V( m+ ?
- 19, 3325, 6, -3, 02 U- y8 ~" S, N6 }! B( j
- 20, 3500, 2, -1, 0$ C" z% B$ k5 e
- 21, 3675, 4, -2, 0+ y& }8 l$ z$ i1 j0 N
- 22, 3850, 4, -2, 0
$ C9 B C5 I) [. H - 23, 4025, 4, -2, 0
7 J# I: d1 q3 d) y) L1 M+ H - 24, 4200, 6, -3, 0+ V7 ~9 q. K3 w3 R% ]
- 25, 4375, 6, -3, 0& A% m/ a; q; \8 F" b. c4 X
- 26, 4550, 4, -2, 02 M: a) Q) x4 E: t( s/ @5 \
- 27, 4725, 6, -3, 0
4 p+ g- @( B: _( u' c8 V, U8 `! a - 28, 4900, 2, -1, 0( I: |3 J& ~; V% F7 J( \" X; S
- 29, 5075, 4, -2, -1% U! [9 j. a# S
- 30, 5250, 4, -2, 0
! ]* l8 ?6 n# i$ n - 31, 5425, 2, -1, 0
6 p4 C S/ p) F9 A/ [% g' \ - 32, 5600, 4, -2, -1
5 j7 v) V8 g" T- m4 L - 33, 5775, 6, -3, -1
7 }1 V) _1 `1 F" @! H4 r - 34, 5950, 2, -1, -1
. J$ N, K i7 L2 C4 F" x& [9 o - 35, 6125, 6, -3, -1
9 M0 P3 [2 V: f2 @ - 36, 6300, 2, -1, 0
: c. Q! b J% e: E' W* o8 ` - 37, 6475, 6, -3, 0
; h& ^1 K7 u; F0 W# v' j - 38, 6650, 4, -2, 0
' ? i1 g0 p; z2 s/ z# z1 Y - 39, 6825, 4, -2, -1# R' ~* u0 ^5 q0 p: \( Y
- 40, 7000, 2, -1, 0
; Z' Z4 l& \5 ]/ p" l - 41, 7175, 6, -3, 06 t: h! e- L1 Q1 c* J% k# k
- 42, 7350, 2, -1, 0
/ j* ^* @* e z3 B0 q* A5 Y% L - 43, 7525, 2, -1, 0
9 @0 R1 ?: w1 O4 W _2 n8 R - 44, 7700, 2, -1, 0
" d: m' l# r0 `- k& n! E - 45, 7875, 2, -1, 09 Y1 H0 G% s; X4 v
- 46, 8050, 4, -2, 0" d% g4 A8 F4 ~8 l
- 47, 8225, 2, -1, 01 p+ \" y* u% B5 n5 E
- 48, 8400, 2696, 1348, 0
, S' }/ n1 h7 p# ] - 49, 8575, 2, -1, -1
1 ~1 S4 k% ^( G5 z, y - 50, 8750, 0, 0, 0; O3 ^9 x. v+ G4 ~2 {
- 51, 8925, 4, -2, -1$ F3 l+ F0 Y. g% m
- 52, 9100, 2, 0, -1; B8 T; N0 g3 s. L2 T# G
- 53, 9275, 0, 0, 0( |6 f9 m; m, J F$ n
- 54, 9450, 2, -1, -1
$ w. L2 `4 O8 N: X# C& k4 ~ - 55, 9625, 2, -1, 0" \/ i8 g: B2 q v
- 56, 9800, 2, -1, 05 B/ r* u6 t+ ?3 p
- 57, 9975, 2, -1, -1
% Q( M6 D' C; q" M F2 V/ I - 58, 10150, 2, -1, -1
2 m" R) S4 I' R - 59, 10325, 2, -1, 0
9 K/ \$ Q: o6 C, _3 x+ e& h - 60, 10500, 0, 0, 0: S0 u3 V0 t( V) t6 e0 Z
- 61, 10675, 2, -1, 0
! x J' L E( l0 }+ v8 b6 T, @ - 62, 10850, 4, -2, -1- ~8 @8 f7 F9 W. r: d3 v" J
- 63, 11025, 2, -1, -18 t& c |/ X, r5 @6 U/ d$ L
- 64, 11200, 0, 0, 0 E% m8 m- f7 e7 a7 A% Y
- 65, 11375, 2, -1, 01 |: b7 b0 z" Y4 F% m
- 66, 11550, 0, 0, 0
+ U+ C) I8 n9 B6 x% E% Y - 67, 11725, 2, -1, -1( z0 t. G) F4 |( D c6 Z" B) e
- 68, 11900, 2, -1, -11 B7 P' W: j) _9 F
- 69, 12075, 2, -1, 1 k( j3 O& \& P8 Z: g1 W" W2 H
- 70, 12250, 2, -1, 1
/ {0 d% X: J/ X" x: } - 71, 12425, 4, -2, 1- y5 h( N2 g' O- [0 @! g/ r# X- J# n
- 72, 12600, 4, -2, -1$ A; a% ?( q4 v7 @6 d
- 73, 12775, 2, -1, 1
% i- w! |* }) J# w+ c - 74, 12950, 0, 0, 0
/ a/ x2 q$ k- x7 Q. M5 s x - 75, 13125, 4, -2, 0' K/ t5 r( L# c' ?8 \4 {
- 76, 13300, 4, -2, 0
; u7 c( `* C) V" W1 |. \ - 77, 13475, 2, -1, 0- }9 y, i! m8 X @# ^
- 78, 13650, 2, -1, 0' g3 b& ?/ f! G$ q) x: S
- 79, 13825, 4, -2, -1
/ q8 `5 V8 |! s w. |4 m( r - 80, 14000, 2, -1, 0' {7 T8 K \! e( ]$ r! n7 \
- 81, 14175, 4, -2, 0
/ d$ Z( a6 a( T - 82, 14350, 2, -1, 1
7 n7 E5 K; x9 T7 p. ^% h - 83, 14525, 4, -2, 1
+ c2 V Q( i* S) p$ T& R r/ ?6 G+ ? - 84, 14700, 4, -2, 1& d2 n: v( L# N. A- B
- 85, 14875, 2, -1, 17 W: g* B& I2 p/ f
- 86, 15050, 4, -2, 0
, I- G" A# J# @7 \, C - 87, 15225, 2, -1, 0
9 f# i4 r* M, t. [/ t W! `) ` - 88, 15400, 4, -2, 1
! d! B# {9 ~& s - 89, 15575, 4, -2, 1
! w" r1 x8 E1 g) z4 M* U - 90, 15750, 2, -1, 0' y3 r9 z7 T7 r1 a _
- 91, 15925, 2, -1, 1& m$ Q5 ]3 C; G
- 92, 16100, 2, -1, 1
- o6 `4 P' L2 u( Z - 93, 16275, 2, -1, 1
' q/ ^# I* u+ l3 ?) B k - 94, 16450, 4, -2, 1, l4 e0 R4 }) b& R# n
- 95, 16625, 2, -1, 1; E( [3 L" `2 P" R: P7 j- {
- 96, 16800, 2, -1, -14 L- U5 |7 T S
- 97, 16975, 4, -2, 0: Y4 i9 o& ^, z- L( v% H
- 98, 17150, 2, -1, 0
" B9 V. o5 f" |2 r) ^9 l - 99, 17325, 4, -2, 0# S! D' C* M- j
- 100, 17500, 4, -2, 16 O4 F( w6 p/ e/ _! h" g/ C
- 101, 17675, 4, -2, 04 z. f" O2 I0 d" N% s$ M; d5 F
- 102, 17850, 4, -2, 1- m a5 ]/ L) p" f( ~
- 103, 18025, 4, -2, -1! |2 B I5 F! k- M" y+ X. V" E
- 104, 18200, 2, -1, 12 q) l! C; R U. q! D
- 105, 18375, 4, -2, 03 `# d5 q- L/ w b' I$ ^
- 106, 18550, 2, -1, 1
- D( ]! \; i% n - 107, 18725, 3996, 1998, 1
|6 H* e4 l; \8 y" r - 108, 18900, 2, -1, 01 S+ L6 V0 h0 x" }5 M
- 109, 19075, 2, -1, 1
6 ^2 Y( q+ v. d3 [3 }& r9 K. W - 110, 19250, 4, -2, 1
' ]3 E4 z1 I2 |& ?' a - 111, 19425, 4, -2, 1: |/ ~! ?! X% S. d% g2 R4 X: T3 a
- 112, 19600, 2, 0, 1
- i# \# l a1 c8 i: w - 113, 19775, 2, -1, 0
$ Q8 T0 Y- i1 J$ ? - 114, 19950, 0, 0, 0
, \. @- _) `: u" D& z# o& Y - 115, 20125, 4, -2, 1/ @$ _1 g- y. k
- 116, 20300, 2, 0, 18 H) O: e4 M$ @0 X4 F
- 117, 20475, 2, 0, 1
' h2 G9 X& r" n( G, I - 118, 20650, 2, -1, 1! H/ y6 ~3 m0 v- l: f+ l
- 119, 20825, 2, -1, 1
. u5 Z8 _- W! [4 `& C - 120, 21000, 2, -1, 1" q, w+ }* H8 i
- 121, 21175, 2, -1, 0
" a' n2 F: u+ m) Y' e - 122, 21350, 2, 0, 1
% m) }) f- N- c% P9 f - 123, 21525, 2, -1, 08 _* x( r! Y4 q* y
- 124, 21700, 0, 0, 0
% }4 A$ S, j# e1 q* b - 125, 21875, 2, -1, 1
7 ^# X+ P N, A4 B' r - 126, 22050, 2, -1, 1/ J* [& _* I/ S) D
- 127, 22225, 2, 0, 1
复制代码 " o# P7 s1 o8 z) _
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。 由以上的实验数据,我们可以看出,在频率为350Hz,8400Hz和18725Hz时,幅值出现峰值,分别为1492、2696和3996,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。
1 {8 i; f$ r* f5 a8 ]& Z' m6 j) O |