|
前些日子,因为需要在STM32F103系列处理器上,对采集的音频信号进行FFT,所以花了一些时间来研究如何高效并精确的在STM32F103系列处理器上实现FFT。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用STM32提供的DSP库这种方法。 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 # ?1 ]; u+ S) m1 b7 e* j
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。 ( C$ D7 K6 t4 Q* i
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库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: - /******************************************************************% D5 y* t! |" j7 S+ a0 E1 \
- 函数名称:InitBufInArray()+ {7 U" ?4 b9 }, R
- 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)
% i4 @7 x7 G6 ^ - 参数说明:& w9 z% W$ W6 |9 e8 X6 _5 s$ V2 U/ U" O
- 备 注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部,% W& M: Q c: }7 d
- 低16位存储采样数据的虚部(总是为0)
7 w8 X( G0 M& `5 g. B6 G l. ] - 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
; F3 V9 y* a/ j9 O9 F - *******************************************************************/) u. m& s0 P! ~& t9 e2 m
- void InitBufInArray()6 x: g/ H; S: B2 b; b1 l( `
- {
# _* v! L6 @7 Y; R4 {3 d: B - unsigned short i;+ o8 k- p: r2 k' k0 r9 j& j
- float fx; l% U: C8 N* E6 L2 c
- for(i=0; i<NPT; i++) r! ] T$ F$ t' w3 a
- {1 O* D4 Z3 b: B: ?
- fx = 1500 * sin(PI2 * i * 350.0 / Fs) +2 b' P8 b2 S ]: w' h2 c
- 2700 * sin(PI2 * i * 8400.0 / Fs) +" @) ]; M/ d) h% b: T U* n
- 4000 * sin(PI2 * i * 18725.0 / Fs);6 _. x; R/ \) t+ }% s
- lBufInArray[i] = ((signed short)fx) << 16;
) d& U/ e0 n. F3 \+ N% x - }2 r8 P4 w* H" n! `+ |
- }
复制代码 4 V6 f, {- w# d
其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。 * U+ M i2 {, T' o9 j4 {7 a9 O
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位存储实部。 ) C8 s0 j" o& W
2.5计算各次谐波幅值 得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。 下面是具体的实现代码: - /******************************************************************" j& L: o" l R" u. f
- 函数名称:GetPowerMag()
) {( V6 H' _, I6 o$ H - 函数功能:计算各次谐波幅值5 F* i# j# A V' v0 b H
- 参数说明:. H4 _ d% C. Y9 b1 X+ n
- 备 注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y)% \8 v7 W' Q: U: T3 u0 i
- 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
" A: n$ P2 m, K - *******************************************************************/
. j% R. w' h1 v3 c7 o5 ^) _2 e; u - void GetPowerMag()
8 ~& R2 h# b+ S' V. f) J - {- d2 E/ f# V9 f1 ~
- signed short lX,lY;
( W) V6 C+ b! h - float X,Y,Mag;
- T0 M2 U3 d/ S- } S! d7 G8 U9 K/ } - unsigned short i;
0 o- M2 f( m& U% ?: v# R) X - for(i=0; i<NPT/2; i++)
: I, D! D( B. D - {2 A1 V/ e. k- u* ^4 `& B" M$ e
- lX = (lBufOutArray[i] << 16) >> 16;
# D& Q3 I! g3 w. M% D1 y$ j - lY = (lBufOutArray[i] >> 16);8 T! t$ X( o- M; l. F2 N) P
- X = NPT * ((float)lX) / 32768;9 a- d }- \& w! _
- Y = NPT * ((float)lY) / 32768;: g( I7 X; K. o: h. ~3 N* p
- Mag = sqrt(X * X + Y * Y) / NPT;6 D% M2 }9 W+ I6 L% ]0 O
- if(i == 0)
' S( i1 R( g4 E! K$ | - lBufMagArray[i] = (unsigned long)(Mag * 32768);
! f d! C+ q6 z - else
) V: ]# e$ \. v4 L% d! N - lBufMagArray[i] = (unsigned long)(Mag * 65536);$ z% b6 @+ H, G g( R
- }
! f$ w C# C! W @. n - }
复制代码
# R- t9 Q3 |# Z8 c# {4 |. w 其中,数组lBufMagArray存储了各次谐波的幅值。 2.6实验结果 通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示: - i, P, Mag, X, Y
, J; }; l% F, p - 0, 0, 4, 0, -4
3 X8 M- E! K& u/ U- z" j" w - 1, 175, 14, -6, -4
, H% R7 Q) w2 A U. X/ c6 P - 2, 350, 1492, 746, -3
2 m: h ~: \: Z, z. `: X' K - 3, 525, 11, -5, -3! u5 s% f! F, Y
- 4, 700, 8, -3, -3
, i% X' {) E9 W8 b5 h0 Z - 5, 875, 8, -4, -2/ m% Y3 X) m$ e0 C4 ^- Q
- 6, 1050, 6, -3, 0
8 ^; \2 c/ s% C) b5 S - 7, 1225, 6, -3, 0
- ?4 @6 s! e; V! V2 Z6 W4 h - 8, 1400, 8, -4, -2* T* w. {; m8 @ i- C2 h3 i9 ^
- 9, 1575, 8, -4, 0% g( b$ b, b; D1 d# H/ h# ?
- 10, 1750, 4, -2, 03 I8 e4 u5 u8 _" D4 v/ }- [( T
- 11, 1925, 8, -4, -1' _5 G1 v, j( x2 }# w9 f
- 12, 2100, 6, -3, 0
) ~. j% ?1 H* j9 ?. J3 x8 r# H - 13, 2275, 5, -2, -2; y( {, Y- C+ T+ K9 D/ d
- 14, 2450, 6, -3, -1# \% \& J2 j2 V( M
- 15, 2625, 8, -3, -3
: x; ]( ~0 a' n7 x - 16, 2800, 4, -2, 0! S2 X1 q2 B# \& a
- 17, 2975, 6, -3, -1% A2 b& N4 J- e9 V! L
- 18, 3150, 6, -3, 0
2 Y7 D6 d' x0 @% ~3 }- T - 19, 3325, 6, -3, 0
+ ^6 _! H2 x2 e( Q& f" g! N - 20, 3500, 2, -1, 04 A* w( L2 v& C5 u6 Q
- 21, 3675, 4, -2, 0
/ b& V- A4 D/ ?: q3 X+ D; K# B - 22, 3850, 4, -2, 0. ?7 C. ]2 h6 y0 R t
- 23, 4025, 4, -2, 0' }& K" [3 z6 p0 c8 Q2 h8 u6 B/ r
- 24, 4200, 6, -3, 0
+ I" S; z7 U, l% _. a: Q: P - 25, 4375, 6, -3, 04 P! n9 @+ t6 }' a( O( B7 l
- 26, 4550, 4, -2, 0- }% c1 L! F) D+ @- q8 _! p3 P
- 27, 4725, 6, -3, 0, b' L5 e, {7 z7 R; p. K
- 28, 4900, 2, -1, 0
3 P. X4 S0 n+ c: z- j4 W - 29, 5075, 4, -2, -1& X* s2 _2 @% F/ g- }
- 30, 5250, 4, -2, 00 e. ^0 j7 V+ T, K- h% V* y5 Q
- 31, 5425, 2, -1, 0
0 W5 V* v- n3 {* r+ Q: U - 32, 5600, 4, -2, -1
7 t+ D- W: A* b3 K5 a) a M5 M - 33, 5775, 6, -3, -1 y( ?1 l' C$ b6 M# \& U
- 34, 5950, 2, -1, -1+ p" e+ n% M# a
- 35, 6125, 6, -3, -1
" J4 D1 \3 @7 W4 t& t. f9 y8 Y& V - 36, 6300, 2, -1, 0
6 R1 J% X6 s# S' y - 37, 6475, 6, -3, 0$ `+ T. r; _. k& c- L) R
- 38, 6650, 4, -2, 0, e- o0 [6 `$ m( n2 L
- 39, 6825, 4, -2, -16 S# C+ { D6 E3 G/ u$ ]+ P; z! W5 z
- 40, 7000, 2, -1, 0 k" I6 c7 p+ N& k
- 41, 7175, 6, -3, 0
" H& L7 c; }/ w* X4 { - 42, 7350, 2, -1, 0! C0 Y" ]6 j- a$ K0 ^/ C3 G
- 43, 7525, 2, -1, 04 W; s4 C( {. n8 H4 {
- 44, 7700, 2, -1, 0$ G' X( \7 Y& P& v: L, p u
- 45, 7875, 2, -1, 00 {3 z' V) T, H. _( t4 P0 G. H( n; b
- 46, 8050, 4, -2, 0
; W: @$ T2 j: q - 47, 8225, 2, -1, 0* k7 ?- a/ U- J, n
- 48, 8400, 2696, 1348, 03 d# k- A% W5 |- c9 V) ^
- 49, 8575, 2, -1, -1# C6 S6 r) N' \) G% b" h% ^
- 50, 8750, 0, 0, 08 R5 `$ f1 ?9 f) m8 N
- 51, 8925, 4, -2, -14 h2 @3 Z+ p. f! E5 D" V
- 52, 9100, 2, 0, -1
, M9 I3 `, Z, z& C+ M - 53, 9275, 0, 0, 04 b$ I! F2 a+ B7 ]' f" {" T0 s
- 54, 9450, 2, -1, -1
" V8 F$ G# v( ~; |, |' B6 F - 55, 9625, 2, -1, 0
5 w$ K& _1 x1 E' h1 ^ - 56, 9800, 2, -1, 0& I9 h! {5 j! R$ L4 b# W
- 57, 9975, 2, -1, -1
6 y* {, }6 B- g+ J - 58, 10150, 2, -1, -1
O$ l2 A; `( t) }$ [' ^* o - 59, 10325, 2, -1, 05 N8 M5 Y1 j. P* r& v t. f
- 60, 10500, 0, 0, 0
1 g& Q1 i. Q; J( h$ W5 D1 _ - 61, 10675, 2, -1, 0
8 M' r; J Y: a& `6 M8 N - 62, 10850, 4, -2, -1: F- e u/ K3 K$ }
- 63, 11025, 2, -1, -1- W1 F# x2 c& Q% L
- 64, 11200, 0, 0, 09 R6 m. Q+ h# A$ f: Y5 t. o
- 65, 11375, 2, -1, 0% m- Y- w$ ?' b( B! L8 B
- 66, 11550, 0, 0, 01 F+ V4 P# F% P, t
- 67, 11725, 2, -1, -16 L; `. `- F$ [ C6 ?; e9 Z2 z
- 68, 11900, 2, -1, -1
6 e Z5 R6 v5 O8 L - 69, 12075, 2, -1, 1
$ F0 L( u# Z; e2 {6 A - 70, 12250, 2, -1, 1, W7 F j D7 C5 {% B/ {
- 71, 12425, 4, -2, 1: C/ _* O/ y5 k6 `: J/ x
- 72, 12600, 4, -2, -18 ?' i7 }9 h( `$ F
- 73, 12775, 2, -1, 1
7 t# y7 A: [2 Y - 74, 12950, 0, 0, 0
9 Y! C; H1 y! G0 w( G' r/ @ - 75, 13125, 4, -2, 0* U2 j, Y/ }) P- ~: |3 ~
- 76, 13300, 4, -2, 0
$ N. p# Q6 H% o - 77, 13475, 2, -1, 00 i. J+ N/ d- f1 z. s. _' `9 L; X! [
- 78, 13650, 2, -1, 0
' x: R/ N' W% U2 _9 [ - 79, 13825, 4, -2, -1
$ G1 N+ u. v: g, l8 [, g6 O2 d - 80, 14000, 2, -1, 0
1 d$ ]( n( g4 E - 81, 14175, 4, -2, 0
/ k! t" j- i# _ y& ]; p: l - 82, 14350, 2, -1, 1
6 E2 F' z7 `7 X% K% ?1 p, s7 w - 83, 14525, 4, -2, 1
2 Y% I) d# M1 n1 m) H - 84, 14700, 4, -2, 1
: r7 N4 k5 [* E+ M* G- e' q0 ` - 85, 14875, 2, -1, 1- O8 p. S9 H8 [- H' ^6 V
- 86, 15050, 4, -2, 0% v3 p( X. A# a% r1 @$ b3 Q4 @8 [& k
- 87, 15225, 2, -1, 0
5 O2 ]. M) I9 [& U' B - 88, 15400, 4, -2, 1
v- V+ D5 n' D( x - 89, 15575, 4, -2, 1
. s$ |0 o; L V6 `4 ]8 V - 90, 15750, 2, -1, 0
4 z' r& G6 O( u: c2 M) j - 91, 15925, 2, -1, 1
+ M. D; A/ r S; H% D% D# I. V - 92, 16100, 2, -1, 1
: n6 a: j: Z. c3 O. f - 93, 16275, 2, -1, 18 ~5 `- p7 _2 N% F4 n
- 94, 16450, 4, -2, 1
( W: s! e4 H/ c v) ? - 95, 16625, 2, -1, 1
" @; T: f3 w3 D- C1 h* ^ - 96, 16800, 2, -1, -1; a+ P' U7 e: _" |7 W
- 97, 16975, 4, -2, 0, W: ?, V0 t4 [# `$ Z
- 98, 17150, 2, -1, 0
: k/ s/ R+ O5 E - 99, 17325, 4, -2, 0
4 ]) G6 J5 U" `& u2 ?5 H - 100, 17500, 4, -2, 1* U4 I1 y1 g' g. }7 l( I+ d5 n
- 101, 17675, 4, -2, 0
[1 u' B; e9 @: F - 102, 17850, 4, -2, 15 n- V0 A' V' l
- 103, 18025, 4, -2, -1
# F& A6 Z4 _% ~6 ^4 K - 104, 18200, 2, -1, 1" C$ E( V& w0 }. `- a
- 105, 18375, 4, -2, 0
- d+ @. {! A9 \- } - 106, 18550, 2, -1, 1
3 v H8 ^% g- r4 m( j$ Y, a4 x - 107, 18725, 3996, 1998, 1# J0 g9 ], n0 B; E8 h1 M
- 108, 18900, 2, -1, 0
; ^* i; U! f/ i" a: _: P - 109, 19075, 2, -1, 13 |( ]( m( I0 u! j' e4 W) _3 S1 {
- 110, 19250, 4, -2, 1; Z& k( x, ^# C/ m
- 111, 19425, 4, -2, 1
3 R. ]7 S( t4 F: k - 112, 19600, 2, 0, 1
- n o$ F# h) L( D; t - 113, 19775, 2, -1, 0+ ~8 Y/ Q6 L5 z! c1 t
- 114, 19950, 0, 0, 0
+ i6 s4 P5 c. S8 @# I0 [ - 115, 20125, 4, -2, 1
) {8 H: T& Y" e( k7 x7 R3 U - 116, 20300, 2, 0, 1% e. [' O. W; r2 l P' f2 f
- 117, 20475, 2, 0, 1
; q7 K: a: Y' e! j - 118, 20650, 2, -1, 1
# m, [" T+ K8 A% I - 119, 20825, 2, -1, 18 L. W/ ~7 c, B1 P+ J/ P( D. |& z
- 120, 21000, 2, -1, 1
3 b2 m) ?9 o- A5 k# I, W4 T3 O - 121, 21175, 2, -1, 0
/ M, Q) V1 N; f - 122, 21350, 2, 0, 1
g- H* f2 N5 w7 I5 i2 O" g6 x - 123, 21525, 2, -1, 0
. @/ f9 r0 j' h" m8 H& l - 124, 21700, 0, 0, 0
% R1 |! b5 u$ [# ]! n - 125, 21875, 2, -1, 1" Y: J6 L2 {" k: N1 |" V& }# R
- 126, 22050, 2, -1, 1
& }1 T4 W( V( k' D( n4 S8 r - 127, 22225, 2, 0, 1
复制代码 - E& Z1 u+ m# g
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。 由以上的实验数据,我们可以看出,在频率为350Hz,8400Hz和18725Hz时,幅值出现峰值,分别为1492、2696和3996,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。 - E& a3 e2 V* o% O& p
|