|
前些日子,因为需要在STM32F103系列处理器上,对采集的音频信号进行FFT,所以花了一些时间来研究如何高效并精确的在STM32F103系列处理器上实现FFT。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用STM32提供的DSP库这种方法。 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 $ w5 b/ U' ^3 }' a* W
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。
& ^4 m( X# q; j/ e" A( J Q2.如何使用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库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: - /******************************************************************+ u9 H2 r: Z+ P6 [
- 函数名称:InitBufInArray()
4 E9 }, M M2 v n7 q - 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)
" e M. H5 L ~% @- _ - 参数说明:
- |* C0 K7 J9 M- A3 g - 备 注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部, m+ |3 l& h- Q8 s
- 低16位存储采样数据的虚部(总是为0)
) Z( s8 Y' H% P - 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)+ z' ~! O+ N$ r3 F
- *******************************************************************/! l7 ~0 p/ I C$ e; ^
- void InitBufInArray()
/ k6 E, x0 [: a) f - {
8 Y) Y* e+ }) Q- v. a, m, [" Z5 S2 E - unsigned short i;
' C6 ~3 H- ]% ] X: j' ~& z) V - float fx;" Y0 q4 |- u! V, `* ~
- for(i=0; i<NPT; i++)
) e) c7 z' z3 }( J - {
$ i/ f+ k2 f$ F" Z& G+ d - fx = 1500 * sin(PI2 * i * 350.0 / Fs) +
% b6 V# W6 P$ {7 X4 H - 2700 * sin(PI2 * i * 8400.0 / Fs) +
. {' E2 ~( z1 E - 4000 * sin(PI2 * i * 18725.0 / Fs);: o2 \: t" r- j: a0 Q+ Z5 V* w
- lBufInArray[i] = ((signed short)fx) << 16;
5 f% P. P; f1 [ ^+ r# R - }
0 _# T5 [" [# [9 R3 U! N - }
复制代码
$ f9 Q2 U: t2 ?" o 其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。 2 ]. [: x% ]: c3 M1 e
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位存储实部。
8 q3 C1 y5 B v4 [6 ~" w$ W# T
2.5计算各次谐波幅值 得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。 下面是具体的实现代码: - /******************************************************************6 G( r% f& E' C0 e7 z5 y
- 函数名称:GetPowerMag(); R# k! q; I6 S% X# r! L
- 函数功能:计算各次谐波幅值
( k' x& I/ }4 ~# e - 参数说明:8 k0 _4 w. S1 u1 u6 P7 g( U1 k
- 备 注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y)
+ I1 h! {6 P& ` - 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)1 w# C" N8 U) J) [7 k
- *******************************************************************/7 i8 u2 O% I& ^1 X
- void GetPowerMag()- x/ k( T+ G6 z) i5 E% X j
- {0 N0 t) p" d2 P# d- i
- signed short lX,lY;- Q$ [4 K% H, j9 \
- float X,Y,Mag;
% g( F1 ?# i. F) b - unsigned short i;
6 y! ?) Y# z2 D" k1 l* U - for(i=0; i<NPT/2; i++)
2 ?. K$ W9 i4 B - {. I( m/ h* {4 Z* t, {' `
- lX = (lBufOutArray[i] << 16) >> 16;
# J, l7 P Z( e* O$ I1 k& Z9 D - lY = (lBufOutArray[i] >> 16);9 I# \, `' z2 D9 z1 P1 `$ X
- X = NPT * ((float)lX) / 32768;
- U' Y! Y; B6 g, y - Y = NPT * ((float)lY) / 32768;
* N/ k$ y' Q/ L+ D - Mag = sqrt(X * X + Y * Y) / NPT;( ]! A5 ?% N, d
- if(i == 0)2 D& m6 J/ L( |5 k' Z) p
- lBufMagArray[i] = (unsigned long)(Mag * 32768);
/ F# K6 ~, |# J! z6 M' F: E - else* P$ W8 X9 `) p
- lBufMagArray[i] = (unsigned long)(Mag * 65536);# M% P- g! H; p( F& G2 R I
- }0 x4 m% e, F& ~
- }
复制代码 * N) h* c3 ]7 F; K& p
其中,数组lBufMagArray存储了各次谐波的幅值。 2.6实验结果 通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示: - i, P, Mag, X, Y
$ K: w0 \0 t& b, b: m0 \& g1 A - 0, 0, 4, 0, -4* E0 A( n( ?. [% d5 y; U# M" @
- 1, 175, 14, -6, -4
7 x5 _5 }% ]) f4 y! ~4 T - 2, 350, 1492, 746, -33 [( ?. W* P" _$ g h8 F5 |
- 3, 525, 11, -5, -3
/ p [+ Z/ B( z9 q0 x( W; B C - 4, 700, 8, -3, -3* E. c1 {3 |5 Z; v/ z( ^) e7 E
- 5, 875, 8, -4, -2
7 T Z9 o' B$ v3 W e8 R! }2 n - 6, 1050, 6, -3, 0
. m$ }2 g' F7 g$ @5 p4 U* z$ n& ? Z - 7, 1225, 6, -3, 0
- M( b- L/ d: O) t( \- k7 {9 _ - 8, 1400, 8, -4, -21 N: z6 {3 u7 t
- 9, 1575, 8, -4, 0
# X. z8 ~4 z& [1 S - 10, 1750, 4, -2, 0
; N2 J& B2 V/ F2 i0 w* ^5 t - 11, 1925, 8, -4, -18 \6 z, W* f; E( `4 {
- 12, 2100, 6, -3, 0; Q- b; [3 p) y- Z: n+ x
- 13, 2275, 5, -2, -26 X" q: }% {. z6 S
- 14, 2450, 6, -3, -1
* \: W' @! @6 l/ O, a6 H - 15, 2625, 8, -3, -3
$ B8 J' k; n5 v% I' [6 x) e# x - 16, 2800, 4, -2, 0
8 t- e; b9 N- {- Q3 R: z! i - 17, 2975, 6, -3, -1# }" v' ?% m# Z3 a
- 18, 3150, 6, -3, 0
2 p( H, A+ L M+ |+ s - 19, 3325, 6, -3, 0. k" t6 ~; r' B' q$ q2 ~0 i
- 20, 3500, 2, -1, 0
6 |0 Y( [1 `+ r: c - 21, 3675, 4, -2, 0, u7 X& |+ U u. T5 y8 z: v
- 22, 3850, 4, -2, 0
9 L2 }" x- }% C, w) a - 23, 4025, 4, -2, 02 S: ?) C3 k) i1 s5 \1 {
- 24, 4200, 6, -3, 0
1 Y# K3 V9 q8 i; S - 25, 4375, 6, -3, 0
9 a( y$ r% h9 q9 ? - 26, 4550, 4, -2, 00 a( Y8 T- u8 N: D: z# V
- 27, 4725, 6, -3, 0
0 p/ o; U& | N - 28, 4900, 2, -1, 09 ?8 v2 }4 {) k- S
- 29, 5075, 4, -2, -18 Y* m% r4 `! O; E4 V0 x7 h
- 30, 5250, 4, -2, 0
3 ?5 A" m# j* @2 x' }& H' T - 31, 5425, 2, -1, 0
& b; T# P1 Y6 Q/ P! H) {$ o - 32, 5600, 4, -2, -18 H4 s2 H% S* l5 K: U2 @
- 33, 5775, 6, -3, -1
. K6 G4 E' Z1 e: l$ e J - 34, 5950, 2, -1, -1
) U% c$ J0 }7 k4 ~; }2 L. m - 35, 6125, 6, -3, -10 g6 ]& ^" Z* `: b/ b/ ] E
- 36, 6300, 2, -1, 0
! k! x2 j) T( X/ o3 W - 37, 6475, 6, -3, 0) N* c7 L+ ^: H c
- 38, 6650, 4, -2, 0
. `+ h6 u: p8 C, u - 39, 6825, 4, -2, -1* _6 H3 P2 e& j t9 F& S+ b
- 40, 7000, 2, -1, 0) U+ S1 `( B( N9 l( Q
- 41, 7175, 6, -3, 0
1 a$ |" {/ I( `8 R' {7 f - 42, 7350, 2, -1, 0
) R, x- x* c' Q7 U - 43, 7525, 2, -1, 0$ { b+ A( _9 v$ {; v# i
- 44, 7700, 2, -1, 0+ x; s8 S7 z# C) b
- 45, 7875, 2, -1, 0, L+ F8 H6 p9 ]# S7 X' a" _5 o9 j
- 46, 8050, 4, -2, 0
& P3 I O8 w# P3 ?. E" l- O - 47, 8225, 2, -1, 0, p5 W, T0 H1 Y3 b% `
- 48, 8400, 2696, 1348, 0; j- n5 G3 X" T H# ^
- 49, 8575, 2, -1, -11 r6 V: h% }, N# |
- 50, 8750, 0, 0, 0
4 Y/ Y' A4 ~1 F4 k" B - 51, 8925, 4, -2, -1) K% z& p9 L. I0 T. h9 z
- 52, 9100, 2, 0, -1$ y& R+ A) q' ]
- 53, 9275, 0, 0, 0
5 |9 R7 i4 @" W0 `" e/ J - 54, 9450, 2, -1, -1" @5 Q# H- M3 `) R
- 55, 9625, 2, -1, 0
. _* n/ p, n7 J- u, v! T - 56, 9800, 2, -1, 05 @, E1 O2 F6 ^9 k# }% Z; G( ]
- 57, 9975, 2, -1, -1. I T. k3 m9 v$ p& O
- 58, 10150, 2, -1, -1
5 `9 b: G0 O; c* @ - 59, 10325, 2, -1, 00 G$ j m4 a; B8 f4 M1 R
- 60, 10500, 0, 0, 0; _2 p, P/ @! P; ^. R- @
- 61, 10675, 2, -1, 0
+ q/ m. a3 a1 I$ H" Q4 Y - 62, 10850, 4, -2, -1. J+ k) L# r2 n9 \: w
- 63, 11025, 2, -1, -1
s/ U5 {/ T5 c7 v4 w0 O7 Y# p - 64, 11200, 0, 0, 01 ?8 t7 K) T( h& r
- 65, 11375, 2, -1, 0- f1 G7 L- ~5 P+ ?4 W% Q
- 66, 11550, 0, 0, 0
% m9 m V3 o3 }6 d7 l5 K - 67, 11725, 2, -1, -1
4 n. J! i3 v0 h - 68, 11900, 2, -1, -10 R- j+ g- g: I* _- \ N
- 69, 12075, 2, -1, 1
T1 j2 F0 M6 W0 k$ U! F6 V - 70, 12250, 2, -1, 1/ Q/ {) r' Y& [4 U. A" y# s
- 71, 12425, 4, -2, 1, Z$ C1 p% t3 \" B; s
- 72, 12600, 4, -2, -1+ @. `0 I" \ S- Y$ M
- 73, 12775, 2, -1, 1
) B! o& V8 Q- M8 t - 74, 12950, 0, 0, 0
; U5 w) A" P/ T# Z+ v5 v9 D9 ]- ?% G; V; c - 75, 13125, 4, -2, 0
' V+ K, X, E2 c. v3 J - 76, 13300, 4, -2, 0- ?1 [6 \7 |9 D B# \
- 77, 13475, 2, -1, 0
0 m$ @! V" u/ [ C6 t - 78, 13650, 2, -1, 0
0 s. A% ?, x0 D2 J% s$ A - 79, 13825, 4, -2, -1- r$ N2 A! ], e' ^2 _5 l @- q1 y
- 80, 14000, 2, -1, 0" y9 C G- I- x: ]4 \' ]' J0 E, }
- 81, 14175, 4, -2, 0, l |4 |& e. a' }8 t8 q1 X
- 82, 14350, 2, -1, 1- V- ?4 i! z4 ]% m& Y5 k% t j8 B! b: d% [
- 83, 14525, 4, -2, 1: x! Z( G; J2 h6 F$ p C
- 84, 14700, 4, -2, 1
0 N6 w5 W) B* ^9 I5 _9 K1 W - 85, 14875, 2, -1, 1( `+ p8 [: i, l7 `. ?; U& e
- 86, 15050, 4, -2, 0
; v& r4 ?" R+ y2 w - 87, 15225, 2, -1, 0* C" M( g9 t! \8 V X' ] c- p; u
- 88, 15400, 4, -2, 1
4 m; c" R1 K4 T1 b0 K o2 g - 89, 15575, 4, -2, 1; @8 N, d, L' i( Z/ j7 g
- 90, 15750, 2, -1, 0' l# i7 g# f. q3 Q0 D2 u+ `- z- F5 J
- 91, 15925, 2, -1, 17 a8 \/ r7 R5 `; P+ B G, a h2 q
- 92, 16100, 2, -1, 1. V& Q$ D) I0 Y& m' x, l3 M2 T
- 93, 16275, 2, -1, 18 y$ \ z- ]; \) c5 f, g
- 94, 16450, 4, -2, 18 x, ], q/ j' h. x* c
- 95, 16625, 2, -1, 1
8 I' n, }7 Y( [8 ~% O - 96, 16800, 2, -1, -1% D4 N- t: \2 a8 ] I+ v. y) ]
- 97, 16975, 4, -2, 0
; b8 w2 ^" S7 I - 98, 17150, 2, -1, 0/ M- \3 R5 e2 B2 K
- 99, 17325, 4, -2, 0" W; a& L% |( i
- 100, 17500, 4, -2, 14 L2 a! O% A9 Y- ]3 _/ p
- 101, 17675, 4, -2, 0) p! P2 Y. |/ X" Z& G6 z
- 102, 17850, 4, -2, 1
9 w$ U2 N; u6 s - 103, 18025, 4, -2, -1
+ D2 n- w5 i8 P7 a( a, N - 104, 18200, 2, -1, 1% l( X. C# ~1 `0 G2 i1 S |* r8 u
- 105, 18375, 4, -2, 0
% ^8 M' Y& e2 k; h - 106, 18550, 2, -1, 1
% Q, e2 g' r6 L/ E, `- d - 107, 18725, 3996, 1998, 1
4 ^1 Q% v: l# l6 Q- t - 108, 18900, 2, -1, 0, F1 v' g2 W/ ] O
- 109, 19075, 2, -1, 1" g7 e0 d+ G2 J/ j/ r& W
- 110, 19250, 4, -2, 1
5 x1 J3 }8 a% U2 d, K; n0 a - 111, 19425, 4, -2, 1
7 `- c* @* ~6 r- o* F# v0 A - 112, 19600, 2, 0, 1
- } j4 }/ t9 i, H# m7 m/ J - 113, 19775, 2, -1, 0) K; P* S) z9 S4 k/ c* A% i" c
- 114, 19950, 0, 0, 0
# O% x# M) z% R9 L1 d9 [ - 115, 20125, 4, -2, 11 s8 P. b! h; Y3 M' k5 B- L
- 116, 20300, 2, 0, 10 k+ U/ ~7 L% `
- 117, 20475, 2, 0, 1
$ r: Q4 F$ F3 b( {" L; g - 118, 20650, 2, -1, 1" }' D' x! M9 W% u4 t& D% {) ]
- 119, 20825, 2, -1, 1& \. ?% B4 u D( A
- 120, 21000, 2, -1, 1( W3 R3 T; R8 [( ^0 ]# y" T
- 121, 21175, 2, -1, 0
8 S6 j; F7 r+ K; J% r - 122, 21350, 2, 0, 1* U& V* C$ j. x- n2 n
- 123, 21525, 2, -1, 06 D. t% q6 C- _9 g; m4 ~+ p0 l S' i
- 124, 21700, 0, 0, 02 W6 Y! t8 i$ P ~* F" ?$ s4 X
- 125, 21875, 2, -1, 19 b4 Z5 m2 K0 C
- 126, 22050, 2, -1, 1
# ^& K* Y" c5 f, v% D: A - 127, 22225, 2, 0, 1
复制代码 ! o, s Z5 g: ?" `8 O
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。 由以上的实验数据,我们可以看出,在频率为350Hz,8400Hz和18725Hz时,幅值出现峰值,分别为1492、2696和3996,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。 5 G$ C: l8 |8 g* [6 W4 {) d
|