|
前些日子,因为需要在STM32F103系列处理器上,对采集的音频信号进行FFT,所以花了一些时间来研究如何高效并精确的在STM32F103系列处理器上实现FFT。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用STM32提供的DSP库这种方法。 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 ! r/ L5 W4 G. H
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。 0 v% e6 x- X- J% W: H) c8 \' @8 N
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库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: - /******************************************************************
0 G/ K, a* O( {2 B2 k8 g" K - 函数名称:InitBufInArray()
4 ^6 U2 z: s5 l# [6 ~' t7 U - 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)
; h, ~7 ^8 T+ d" H/ P3 O0 Z' D2 V - 参数说明:) c P* V3 Q3 \- |' r
- 备 注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部,* ]/ n$ v& M9 c8 d( s
- 低16位存储采样数据的虚部(总是为0)
3 g, I. P5 y% u$ V t - 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
4 c. j" |/ \, X& ? - *******************************************************************/. K% M4 I( r. Q7 j7 |) v
- void InitBufInArray()
5 T. F& i+ {2 G; F( X% U - {" d/ s: t/ D- `# n
- unsigned short i;
- S/ X& l2 a: v9 h. u - float fx;
" r6 R0 p$ y; f9 N3 B& s- t - for(i=0; i<NPT; i++): `$ b' y1 q6 P, S1 P
- {. a$ ]0 ^3 o8 |' |
- fx = 1500 * sin(PI2 * i * 350.0 / Fs) +9 D4 ?" Q% M2 A. Z) B. |
- 2700 * sin(PI2 * i * 8400.0 / Fs) +& J: |# d5 _; T/ b# o
- 4000 * sin(PI2 * i * 18725.0 / Fs);
, K3 ]) k! N S4 |" @ - lBufInArray[i] = ((signed short)fx) << 16;8 s6 [& z- Y# b5 E
- }7 q6 U" q" z3 r/ w: Q4 U1 e- d
- }
复制代码 : W% h$ X# S7 A8 R- y
其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。
! u1 P ~/ F6 z y; q$ 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位存储实部。
; r+ ?( B) ?+ l# z7 X2 B
2.5计算各次谐波幅值 得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。 下面是具体的实现代码: - /******************************************************************
* J/ `$ ]: D# G6 l - 函数名称:GetPowerMag()3 X% w& @9 j0 Q+ D
- 函数功能:计算各次谐波幅值
7 V! m9 h$ E; ^/ ~ - 参数说明:
3 t& R' _7 E5 K# A, H - 备 注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y), v0 R, E( ]& E0 [ N3 t
- 作 者:博客园 依旧淡然(http://www.cnblogs.com/menlsh/)8 |, {( L$ |, z/ |- X* r f& p ]% m0 A
- *******************************************************************/# p' | k: ^$ I3 |% z8 n M
- void GetPowerMag()
% X, b7 k D( I; D - {
0 R. u$ K, H$ G( {9 l: m' J - signed short lX,lY;! f2 S# |8 v/ w, d7 @$ M
- float X,Y,Mag;
# \7 N9 S8 I" b& r& x: X# Q7 t - unsigned short i;5 e# @4 J# |0 o" M' a2 X
- for(i=0; i<NPT/2; i++)
6 \* }+ f( c$ p: ^ - {; V. G/ R9 Y$ r8 a9 A
- lX = (lBufOutArray[i] << 16) >> 16;
% g/ D x: u' Y8 e3 c, [ - lY = (lBufOutArray[i] >> 16);
1 g* I: W6 H8 N: j - X = NPT * ((float)lX) / 32768;! x! @! w) x$ y/ H! Y
- Y = NPT * ((float)lY) / 32768;
' e4 U B3 N0 p N - Mag = sqrt(X * X + Y * Y) / NPT;* a" z4 b- k$ m$ u, G" h# Z# L
- if(i == 0)& R: w4 B/ Q q* a$ a
- lBufMagArray[i] = (unsigned long)(Mag * 32768);4 ~: g3 C' M0 T- L/ S( t9 e
- else
; D/ X9 @6 U0 A( j8 w - lBufMagArray[i] = (unsigned long)(Mag * 65536);/ w4 \+ k, C7 S$ [& B
- }* s# \, O6 j1 j/ l: E; D
- }
复制代码
6 u$ @! I P) p; b0 k9 H5 R 其中,数组lBufMagArray存储了各次谐波的幅值。 2.6实验结果 通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示: - i, P, Mag, X, Y9 A0 }" i: @- c4 T# r) ^7 n
- 0, 0, 4, 0, -4
% } K. b3 I1 x- ^+ m) E% |5 Z - 1, 175, 14, -6, -4
O4 d5 `# l6 x - 2, 350, 1492, 746, -3
9 t/ G( K' R# @! O9 v+ A - 3, 525, 11, -5, -3
. w7 r6 I/ T3 m0 ?) }, [' W& f - 4, 700, 8, -3, -3! Y: Z* }0 _3 k, y
- 5, 875, 8, -4, -27 I$ v1 d( s8 x
- 6, 1050, 6, -3, 0
" d, |3 h; a+ b" h# }: ` - 7, 1225, 6, -3, 0/ ]. w2 z0 A9 s% x! [9 W
- 8, 1400, 8, -4, -2
, W/ }7 r' f" O% e0 f - 9, 1575, 8, -4, 0
7 E# X8 o# s! q) B4 w - 10, 1750, 4, -2, 0
g0 D1 c0 {+ _ - 11, 1925, 8, -4, -1
3 c$ Y+ [' k* { - 12, 2100, 6, -3, 03 W: I4 x1 ~( k. I& ?; g
- 13, 2275, 5, -2, -25 w" A! ?9 \( Z b {
- 14, 2450, 6, -3, -1
4 p8 I! B5 O1 G4 q- T+ ^: m - 15, 2625, 8, -3, -3( q9 E: u4 B. b( X; p- d; b( d
- 16, 2800, 4, -2, 0
4 Y& z6 S! b G& A - 17, 2975, 6, -3, -1! N9 |2 t$ [# Q( a+ N
- 18, 3150, 6, -3, 0$ s! ?7 t6 X" j4 k1 U. r( C
- 19, 3325, 6, -3, 0
: l6 d+ d8 O5 k% M - 20, 3500, 2, -1, 0
: e. p- k6 Q. ~# z - 21, 3675, 4, -2, 0. q9 Z3 f. @# C6 ~5 @7 d6 M! [, e
- 22, 3850, 4, -2, 09 ]+ ?8 C ]7 G, e
- 23, 4025, 4, -2, 07 A) U; E' N1 c6 I7 C
- 24, 4200, 6, -3, 0
* O* x# O ^. D4 D! N8 G. ^% i - 25, 4375, 6, -3, 0' d! I2 a! c) W1 A; M& z) Y2 A
- 26, 4550, 4, -2, 0% G( U& Z9 X" C/ ~' C( y
- 27, 4725, 6, -3, 0$ v* A# Z% J+ p! H
- 28, 4900, 2, -1, 0
/ ^6 ~0 t8 i/ n& M - 29, 5075, 4, -2, -16 S$ z; q# \6 D$ ?+ {
- 30, 5250, 4, -2, 0
: [/ q) `. L7 B- Q7 h8 D5 D - 31, 5425, 2, -1, 01 t! W" I" G. P, A$ M6 v
- 32, 5600, 4, -2, -1
! { @& ^2 u$ ]9 ^0 [ - 33, 5775, 6, -3, -1' S- s4 U' c! @( s0 N" j
- 34, 5950, 2, -1, -1
: h; O+ t2 J' w' |7 ?: m - 35, 6125, 6, -3, -1" S( e* w1 C+ |- R; h
- 36, 6300, 2, -1, 0. l& A& a- j R- Q, p
- 37, 6475, 6, -3, 07 g- n5 Z; k* J) p6 l: R
- 38, 6650, 4, -2, 07 Q- c( K, `: l) k
- 39, 6825, 4, -2, -1
) J. K- X7 j, _; b! r - 40, 7000, 2, -1, 0
, x* u: b8 F5 U" u; G" y - 41, 7175, 6, -3, 08 _1 N# }# \9 t( h4 F0 ~. ~) q
- 42, 7350, 2, -1, 0& N \# H8 e& l8 G% n! I0 S
- 43, 7525, 2, -1, 0+ r& {0 {* ~* {7 ^
- 44, 7700, 2, -1, 0
8 V' D- @! X9 G4 ^, l$ I0 `% H - 45, 7875, 2, -1, 0; O w! `9 L* m& ?
- 46, 8050, 4, -2, 0
0 W+ U, @( \6 h- i u - 47, 8225, 2, -1, 04 E" [) P6 k; d0 r& j2 Q! v2 H
- 48, 8400, 2696, 1348, 0
. F/ U7 {; r' {- f# ] - 49, 8575, 2, -1, -1
}, ^3 v1 R: z2 O, T - 50, 8750, 0, 0, 0
7 g& u) S/ ~" {6 C/ N$ w+ N( U5 W - 51, 8925, 4, -2, -1
# @( Y& }3 z/ a8 a! ?0 F - 52, 9100, 2, 0, -1
6 G! W* |, t3 P0 S0 H4 ]/ { - 53, 9275, 0, 0, 0
# p: t9 Y! d& O+ X" V: t - 54, 9450, 2, -1, -1; I8 o2 o7 s5 z/ d4 U! H
- 55, 9625, 2, -1, 03 r2 s. s8 Q: J7 Q) K
- 56, 9800, 2, -1, 0
* W- m' B, d) t - 57, 9975, 2, -1, -12 T6 @" b3 W' _: ?
- 58, 10150, 2, -1, -15 r$ |& j5 P5 l$ ^" ?9 `
- 59, 10325, 2, -1, 0
) ]8 g6 e; E1 M; T$ \ - 60, 10500, 0, 0, 0
; b! x# [; t, X8 n6 e* U% H - 61, 10675, 2, -1, 0
: A# I9 B% V4 h6 D# l$ \* s - 62, 10850, 4, -2, -13 g( E7 C( y! ?* X
- 63, 11025, 2, -1, -1' M" h9 n; n7 q. V4 O
- 64, 11200, 0, 0, 0$ S( ~3 z% K/ y0 i; x4 ?$ j
- 65, 11375, 2, -1, 08 K' I+ e- c" @
- 66, 11550, 0, 0, 02 v5 w) J" _% n% W4 C6 m( w1 B
- 67, 11725, 2, -1, -1
& W7 |# ]# S) Y- g- p. Z% L - 68, 11900, 2, -1, -1
E" A4 p q6 M- q2 p - 69, 12075, 2, -1, 1- k4 p3 p3 i: v1 G) y& l( i7 ~
- 70, 12250, 2, -1, 1
, O, ?, M% T" A( t2 v2 a - 71, 12425, 4, -2, 1
. Z, {! e$ e3 s% D0 @" m2 f8 I - 72, 12600, 4, -2, -1
4 H# B5 l! `; A5 X3 I+ ] - 73, 12775, 2, -1, 1
- W$ x* V) h: O( {0 A) w& N - 74, 12950, 0, 0, 0% [4 h1 {* F. S1 @( W; ]
- 75, 13125, 4, -2, 09 d; p$ M4 d. S" y- z! e
- 76, 13300, 4, -2, 0' | z" J. N# s1 D. a- r
- 77, 13475, 2, -1, 0
q. Z/ h* s" q4 [0 n( K - 78, 13650, 2, -1, 05 I! M- ^2 o% E) m) a- k2 a
- 79, 13825, 4, -2, -1. z, |9 [% O& S$ t# M( @. i
- 80, 14000, 2, -1, 0
8 E0 z1 @$ O) d: M2 Q. W7 {: I - 81, 14175, 4, -2, 0
1 T$ i8 e' K- S - 82, 14350, 2, -1, 1, h% c+ R/ P0 C- I! x
- 83, 14525, 4, -2, 1
' `4 z6 i5 A) F1 F* |% B/ F - 84, 14700, 4, -2, 1% c( S7 u$ e( s" l
- 85, 14875, 2, -1, 11 w. s7 i3 }) Z: k
- 86, 15050, 4, -2, 0
, R1 N( t8 x3 i! D% Z' g" [ - 87, 15225, 2, -1, 0
( S5 n+ e% ~6 R - 88, 15400, 4, -2, 11 x9 l0 k9 _9 ]9 V' ?/ A
- 89, 15575, 4, -2, 1# F# E) M5 H& N7 K
- 90, 15750, 2, -1, 0
/ _/ H. V) e9 w0 G( |& b9 \ - 91, 15925, 2, -1, 1
: U* z: \! V2 T - 92, 16100, 2, -1, 1/ p' X/ n, f# ]9 k) t9 Z
- 93, 16275, 2, -1, 1
5 J' l9 O$ [: q( h+ ? m2 A - 94, 16450, 4, -2, 15 r' x M/ W E- K9 p3 M% a: Y
- 95, 16625, 2, -1, 1- @: M% Q3 {% x& s. s& e) p; \
- 96, 16800, 2, -1, -1
& b5 F9 T7 B( {3 B - 97, 16975, 4, -2, 0
2 G/ t9 E: V( R* X! ?( c! P7 } - 98, 17150, 2, -1, 0
* h" t9 t% d1 ]" M - 99, 17325, 4, -2, 01 b% p8 b" t X% d/ w* b3 b
- 100, 17500, 4, -2, 1
3 w( ? _/ j" G0 l5 m - 101, 17675, 4, -2, 0( `4 _8 I' i8 o
- 102, 17850, 4, -2, 1( C; p. C/ | d5 M! [2 ~$ L
- 103, 18025, 4, -2, -1& f# K* v# T# a( P1 d& m
- 104, 18200, 2, -1, 1: {" T! S: O9 H8 k5 J( b$ g( s
- 105, 18375, 4, -2, 0
5 T, L4 f% R+ y7 h G - 106, 18550, 2, -1, 15 q9 I( N H# Z, x4 q- j% q
- 107, 18725, 3996, 1998, 1
* l# z. u5 ?2 F( `" Q - 108, 18900, 2, -1, 0
2 v3 x& X, b4 x0 ~) ] - 109, 19075, 2, -1, 1
H5 o2 H0 C4 Y, N$ m - 110, 19250, 4, -2, 1
2 ^) e0 i& z" l. ?" G7 h5 j - 111, 19425, 4, -2, 1
- q7 `% f; p' Y8 W2 q3 I - 112, 19600, 2, 0, 1
8 V2 ?1 ]: ^! ~9 v( V4 z) K+ U - 113, 19775, 2, -1, 0
) G7 V8 Q- h4 ~ - 114, 19950, 0, 0, 0
# w. F/ K S$ W- v U0 t" b - 115, 20125, 4, -2, 1' D- `# B* z& d+ f
- 116, 20300, 2, 0, 1) Q% b6 n4 a# _9 j* M
- 117, 20475, 2, 0, 11 u/ e# I0 s' ^ U: q9 B
- 118, 20650, 2, -1, 1
$ H5 K* H3 M, V$ j - 119, 20825, 2, -1, 1
& e9 E* S' Q4 O6 B - 120, 21000, 2, -1, 1, ]8 @% B/ C/ A/ V( |3 y
- 121, 21175, 2, -1, 0
- I" j+ l- h5 y' I& y - 122, 21350, 2, 0, 1+ m" U1 ]9 G: ^: J* y3 H3 S
- 123, 21525, 2, -1, 07 F; }8 h0 C, T+ V/ ^' z7 f" N$ v
- 124, 21700, 0, 0, 0' d$ w8 j X$ w/ j2 o" e3 _, ~. k9 ^
- 125, 21875, 2, -1, 17 ~& R8 `5 b. F0 P" x$ Y
- 126, 22050, 2, -1, 1
/ {, ] W) l! f" n1 z$ [. v - 127, 22225, 2, 0, 1
复制代码 U) g% \; Y6 P7 v- e$ v: J8 R
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。 由以上的实验数据,我们可以看出,在频率为350Hz,8400Hz和18725Hz时,幅值出现峰值,分别为1492、2696和3996,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。
# ]0 }- L# e( w i |