前些日子,因为需要在STM32F103系列处理器上,对采集的音频信号进行FFT,所以花了一些时间来研究如何高效并精确的在STM32F103系列处理器上实现FFT。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用STM32提供的DSP库这种方法。 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 1 s- g. n% _. K
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。
3 {4 X& d- o; i2.如何使用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库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: - /******************************************************************
2 {% F0 E6 ]3 f6 c4 c% F3 { - 函数名称:InitBufInArray()- |% x- _, N4 @" i, |/ Z
- 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)
/ D* K5 s: I5 ?3 @" V - 参数说明: u7 o/ u/ @2 i: h) @* }
- 备 注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部,1 g8 _9 f. w" h
- 低16位存储采样数据的虚部(总是为0)$ |1 E5 N: r1 @# _
- 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
7 l8 [3 m! Y& g. Y - *******************************************************************/$ x {. P) f- ]1 @
- void InitBufInArray()6 r# X: b: j8 z2 m3 N
- {
6 B! E* o0 I( r+ C - unsigned short i;& _6 f2 c! l! P1 ~4 k4 z6 C2 Q; v
- float fx;
; g1 a- n9 ?: K! M) M a - for(i=0; i<NPT; i++)
2 h9 E" N/ [9 ?" Z) W1 O! ^ - {' }2 I0 |! r* I$ X
- fx = 1500 * sin(PI2 * i * 350.0 / Fs) +, G9 @/ W3 j" T( N+ i
- 2700 * sin(PI2 * i * 8400.0 / Fs) ++ J t6 d0 B" z2 r" Z/ z
- 4000 * sin(PI2 * i * 18725.0 / Fs);0 v Z$ M; a7 p7 H
- lBufInArray[i] = ((signed short)fx) << 16;
% t$ Q# a! V t" k4 \8 V - }' J0 X; @( F1 Q$ \, H% E
- }
复制代码 6 f, q6 e$ i" Q, Z6 h
其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。 # R7 N6 e6 E0 N7 Z
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位存储实部。 0 `3 a) I6 I/ ?3 _
2.5计算各次谐波幅值 得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。 下面是具体的实现代码: - /******************************************************************( V+ I& n D- \- s8 \
- 函数名称:GetPowerMag()
# M& |" h8 j0 L - 函数功能:计算各次谐波幅值
7 U% Q3 x$ p- L; L8 { - 参数说明:( G' P4 q4 k- z/ q6 ^8 D+ M M
- 备 注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y)
9 S2 C' u* L) F9 J8 K - 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
C" B, [' s, Y# K9 U6 { - *******************************************************************/
+ ], t% g9 n N9 J7 t: k! l- C - void GetPowerMag()
. b% a! f- k, V. E/ }" @9 b - {
( M" o, |' ~7 X" V4 n* G - signed short lX,lY;
& n A) E5 ` |1 l' B, I' {- c - float X,Y,Mag;
1 z7 j9 r& W j3 E. K - unsigned short i;
3 [3 D+ E/ X9 I! r5 G+ ?: F - for(i=0; i<NPT/2; i++)
0 x, w5 L: c# X+ d- B4 P - {' j0 U. M, X4 ]
- lX = (lBufOutArray[i] << 16) >> 16;
! V0 a- A0 A4 |$ w - lY = (lBufOutArray[i] >> 16);
* d6 T- s# J& B6 m4 V5 |( U" e, f - X = NPT * ((float)lX) / 32768;
( q/ O0 q# E2 N) l - Y = NPT * ((float)lY) / 32768;
; K& {+ |7 T7 T3 s - Mag = sqrt(X * X + Y * Y) / NPT;6 e/ `$ r0 Y: ^: o
- if(i == 0). A6 a* K, V7 |3 Z5 M2 ?6 b4 Q! _
- lBufMagArray[i] = (unsigned long)(Mag * 32768);8 P' D. _7 E/ B1 @/ [/ D5 a6 j+ T
- else( t, v1 T: Z" T2 B
- lBufMagArray[i] = (unsigned long)(Mag * 65536);9 l4 K+ B0 v; F1 c! S- V& J
- }# a1 e9 b: z/ @! S% y& r
- }
复制代码
1 L) [% f h/ A- U8 Y 其中,数组lBufMagArray存储了各次谐波的幅值。 2.6实验结果 通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示: - i, P, Mag, X, Y
: p# X4 r Y7 w9 h2 z+ S. \5 ` - 0, 0, 4, 0, -4
% ~: w) K; b8 v; V+ z7 ^5 I4 ` F - 1, 175, 14, -6, -4
; X \" z& N% u5 a% p! } - 2, 350, 1492, 746, -3
+ N$ _8 z2 m! U7 X8 j* @ - 3, 525, 11, -5, -3
5 K8 ~: X K. O2 H/ c; A! e7 f - 4, 700, 8, -3, -3
0 a" n2 k( K+ N; s! a% o - 5, 875, 8, -4, -2
4 N& ~% ~% i% _/ t - 6, 1050, 6, -3, 06 H$ l3 u# p! I0 V
- 7, 1225, 6, -3, 0
- X0 e' _6 m. F0 j2 h; Z* E e, Q - 8, 1400, 8, -4, -22 D# e' I; a! p, |
- 9, 1575, 8, -4, 0* D9 q; s+ y, \, n9 R% A
- 10, 1750, 4, -2, 0
8 Q/ Y9 ?. H" s - 11, 1925, 8, -4, -1" R1 k( E/ P9 J' O
- 12, 2100, 6, -3, 0; T. x0 j$ r( h( z( |7 g; R) A
- 13, 2275, 5, -2, -2
8 J4 w' b1 a7 U" ^9 o - 14, 2450, 6, -3, -1. |; Y2 Z: e# z' [
- 15, 2625, 8, -3, -3
# L/ r- b- e2 }0 r. f - 16, 2800, 4, -2, 0
4 O4 F& x6 _6 N - 17, 2975, 6, -3, -1
5 y$ i- m6 }0 D' c3 w8 t. x - 18, 3150, 6, -3, 0
, ]; {2 ^# n4 A. \; W* t - 19, 3325, 6, -3, 0: F, a/ @& h; ^# X: r$ A$ F
- 20, 3500, 2, -1, 0. k+ w& i4 i: s5 a ]2 A2 R. T6 Y' s
- 21, 3675, 4, -2, 0, O2 U# H& d4 X: |; V- T5 ^
- 22, 3850, 4, -2, 0
/ W' P0 R8 Q |4 f7 p6 T2 r - 23, 4025, 4, -2, 0" c8 V8 d' Y) p5 H% ~
- 24, 4200, 6, -3, 0 k# ?7 V% i. ^, I9 f
- 25, 4375, 6, -3, 0& I* |; B/ |( x) C, _" b
- 26, 4550, 4, -2, 0& K% T8 a2 t) S/ Q) W8 L
- 27, 4725, 6, -3, 0
( ^6 x9 ~4 S3 \. ^" K2 ~ - 28, 4900, 2, -1, 01 S0 V8 T7 x/ K) b; W( ]9 ]2 c6 J
- 29, 5075, 4, -2, -1/ Y2 C9 [/ s. d4 }5 X
- 30, 5250, 4, -2, 0; `5 S- N5 A. j
- 31, 5425, 2, -1, 0+ b/ N5 q# G9 F
- 32, 5600, 4, -2, -1" S7 B9 J; g- l f7 Z) ?
- 33, 5775, 6, -3, -1; R4 J) h% T; o' s! c: f: N
- 34, 5950, 2, -1, -1
2 Q* T. ~6 F% x, a# R - 35, 6125, 6, -3, -1
( R3 ~* T1 J8 b0 ] - 36, 6300, 2, -1, 0
8 g) D/ r( B2 {0 D1 W - 37, 6475, 6, -3, 03 r- `; j t0 M$ X. h
- 38, 6650, 4, -2, 0' L) o5 x4 O! D7 w; S% }
- 39, 6825, 4, -2, -1
7 l' ^; k( e# g& p, H; V! Y" ^ - 40, 7000, 2, -1, 0+ f. d' D# n7 l' h: ~, C
- 41, 7175, 6, -3, 0' e3 B/ Z0 C2 S- p# f; E
- 42, 7350, 2, -1, 0
# B& G) N0 z! M( ~5 p7 p4 |, Q6 n - 43, 7525, 2, -1, 0
2 N0 s' K6 R' c" ]( |5 e- k - 44, 7700, 2, -1, 0! e8 z6 n) W5 F" H8 D
- 45, 7875, 2, -1, 0
! T& f: Y4 ?" u% b - 46, 8050, 4, -2, 01 z6 T: `+ _# p7 R3 A7 a' ~( N
- 47, 8225, 2, -1, 0
' m$ W5 u, B% o- W0 T - 48, 8400, 2696, 1348, 0 Y/ [. p/ J; S K( O
- 49, 8575, 2, -1, -16 q) z+ m# |) g' M$ b! }9 S, O
- 50, 8750, 0, 0, 0/ p7 k2 A! T/ P
- 51, 8925, 4, -2, -16 E8 n8 N) ~! g a& J
- 52, 9100, 2, 0, -1, i ]4 F0 |1 |+ b
- 53, 9275, 0, 0, 0
' G, ^( T) z! h& j# _ - 54, 9450, 2, -1, -1
. G8 v2 q% p7 [6 M6 e - 55, 9625, 2, -1, 0
. _& h( F( P' X6 A$ Q) U, ` - 56, 9800, 2, -1, 0: K& N0 W, f/ P1 Q; i' I
- 57, 9975, 2, -1, -1
& M. G. x. B$ u" |+ m6 e - 58, 10150, 2, -1, -1
0 p; L, F) T$ ? - 59, 10325, 2, -1, 0, r- D. i5 g) K3 E/ k% ~& g9 W
- 60, 10500, 0, 0, 0* N5 p0 w& b# s- x
- 61, 10675, 2, -1, 09 i- P. M% n" Y! v6 P& z* I
- 62, 10850, 4, -2, -1( ^* \6 p+ @# T4 Z v% Q0 H
- 63, 11025, 2, -1, -1
7 s+ e( G' n3 R: R+ v - 64, 11200, 0, 0, 0
9 W; x: U4 w1 j - 65, 11375, 2, -1, 0
0 M5 o/ y3 d; e4 ? - 66, 11550, 0, 0, 0! {/ G/ p& m5 s& r% Y' p
- 67, 11725, 2, -1, -1
; I" A8 Y' |! b, x% l K8 ] - 68, 11900, 2, -1, -1
0 S8 O' F/ k+ ^, {' k$ W" A - 69, 12075, 2, -1, 1
1 p f7 ^6 F, d - 70, 12250, 2, -1, 1& t9 m1 m0 g8 A
- 71, 12425, 4, -2, 1# O; d) Y7 T- H5 c
- 72, 12600, 4, -2, -1$ g, [/ H( n9 G: ]$ R
- 73, 12775, 2, -1, 19 D2 t+ K* M6 k+ v6 J
- 74, 12950, 0, 0, 00 A* g) p" ]" c/ |2 E6 n0 r
- 75, 13125, 4, -2, 0' r" W$ r; R6 A" T, v- q3 A' |* d
- 76, 13300, 4, -2, 05 @* F0 V6 y8 s- `5 o9 x
- 77, 13475, 2, -1, 0
0 P# U: U6 E) A) I, |. V - 78, 13650, 2, -1, 0
|# y. E+ e/ b& D - 79, 13825, 4, -2, -1( a/ v8 @6 \2 v0 J
- 80, 14000, 2, -1, 0
) G7 z4 L0 Z: C - 81, 14175, 4, -2, 0
: B9 ~1 O& K, [6 B - 82, 14350, 2, -1, 17 s7 d+ z: j7 e2 C4 e4 s3 w
- 83, 14525, 4, -2, 1/ x" {' |3 _& z7 K$ s" b7 N
- 84, 14700, 4, -2, 1+ x% E1 _! x- D- W h6 m
- 85, 14875, 2, -1, 1
5 s+ M8 V, c. m' E% v6 _9 p* P - 86, 15050, 4, -2, 0
$ x: ^- W( Q- `" @ - 87, 15225, 2, -1, 0
5 b T! |( q: F; |! V1 e$ Z1 j5 a - 88, 15400, 4, -2, 1
; X6 S/ W4 `/ U6 z" _! L - 89, 15575, 4, -2, 12 ?* Z! n* N4 O- k: c
- 90, 15750, 2, -1, 0' p; e3 l$ b+ i( r9 ?5 e% E6 H+ ^2 V
- 91, 15925, 2, -1, 1
2 {1 ~" D& n% q. P r! z N; {$ ` - 92, 16100, 2, -1, 1
% B% T- R( w) Q$ m$ l# N- U7 h& y - 93, 16275, 2, -1, 1- @6 X B' I: k, }+ G* H0 v' v
- 94, 16450, 4, -2, 1/ U: t A7 n, o5 S
- 95, 16625, 2, -1, 1, \+ r4 z' ]* X; z- H
- 96, 16800, 2, -1, -1/ u% h% {) S) v$ j/ Y" g. r* U
- 97, 16975, 4, -2, 08 e$ \2 d: X8 E& s) z+ G
- 98, 17150, 2, -1, 06 x" Z% a4 T- g; k/ m9 s
- 99, 17325, 4, -2, 05 s5 p' R: @2 ?- U
- 100, 17500, 4, -2, 14 n! S7 T _# |5 S
- 101, 17675, 4, -2, 05 p) `# C4 ~* q% r4 K. J
- 102, 17850, 4, -2, 1
# Y/ d9 o* N* r+ n6 A - 103, 18025, 4, -2, -1
^) u/ ]; [( R3 |. j - 104, 18200, 2, -1, 1
1 ]* ^7 j' G& L8 d# m' o! [ - 105, 18375, 4, -2, 0( s6 `) e. B. [
- 106, 18550, 2, -1, 12 i, X/ y4 I B# ^! ~: s' O
- 107, 18725, 3996, 1998, 1
9 F. i% U) m9 n4 L7 T! M1 ?* j - 108, 18900, 2, -1, 0
3 h1 I; r) P! E1 {5 E( v - 109, 19075, 2, -1, 1
7 a- C4 q I7 v1 k+ g - 110, 19250, 4, -2, 1
5 q& o, b$ Z% O8 X - 111, 19425, 4, -2, 1! q- }+ s3 @# g8 U4 q
- 112, 19600, 2, 0, 1
* h# e+ g7 J3 m- e8 D% y- P - 113, 19775, 2, -1, 0 W" N" k! B: R9 I
- 114, 19950, 0, 0, 04 V8 }3 ~2 H' X, O T B
- 115, 20125, 4, -2, 11 A$ u" c( D: j6 U' c
- 116, 20300, 2, 0, 1
6 R- s7 Q+ K8 A6 Y - 117, 20475, 2, 0, 1
8 b3 S0 f+ c' J" Q - 118, 20650, 2, -1, 1) ]5 ?% t7 k/ U a4 o* |; B# \
- 119, 20825, 2, -1, 1
: K0 T9 e+ Y2 X/ r5 [ - 120, 21000, 2, -1, 1
& `+ C! u! z; {; X8 \9 d - 121, 21175, 2, -1, 0
+ E/ W, \- W. s- H+ Z3 n0 \! B! K - 122, 21350, 2, 0, 1
$ [: i \$ K# W- a2 L0 [# ?: [* t - 123, 21525, 2, -1, 03 }: c5 n/ F) @& U
- 124, 21700, 0, 0, 0& |6 e b8 d" g/ [
- 125, 21875, 2, -1, 1# W; K; T" B1 _& }; A
- 126, 22050, 2, -1, 1% q) y. T7 [: x' E+ q; h3 ^
- 127, 22225, 2, 0, 1
复制代码 & L, Y9 K$ F! d$ o, S/ W2 q, n
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。 由以上的实验数据,我们可以看出,在频率为350Hz,8400Hz和18725Hz时,幅值出现峰值,分别为1492、2696和3996,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。 5 C- f5 V8 t; L7 V: q) m
|