前面是关于怎样运行fpu的,以及相关的环境配置" w6 S A( i( g: n! ^
) s F6 c# o) [+ bFFT的测试) `% Y8 e1 M I- `8 z
先看一段关于官方的FFT测试例程
. p% b, L1 i: ?- ~/ n里面添加了相关注释
. J9 @3 _* @$ o6 k7 S, G; ]6 G$ T! Y2 W) @ ]
- #include "arm_math.h"
) J6 X. K9 e, W! g4 t d - #include "arm_const_structs.h"3 T: S& W0 `, M$ k& E1 w8 H _6 E
- W. F! N5 T1 A( I( O1 m, s _; y- #define TEST_LENGTH_SAMPLES 2048
$ X; C* s7 K E+ D! c) q# B5 X - : W/ ]6 G5 Q2 \) G% m! V
- /* -------------------------------------------------------------------- j0 U( B* R0 q4 p" |
- * External Input and Output buffer Declarations for FFT Bin Example
/ t3 [# a: S9 ?4 c$ r1 U: L - * ------------------------------------------------------------------- */
. k/ ?" j1 o1 y - extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];
- W! u; g2 W( K; F: k5 n8 f& | - static float32_t testOutput[TEST_LENGTH_SAMPLES/2];
# f- o# a4 J2 P: x/ [, T- v" s% O
5 d1 A( b3 V/ Q* w. A- /* ------------------------------------------------------------------, f/ x+ N0 G: ?7 U% X
- * Global variables for FFT Bin Example
% ~9 q2 P; I4 W. n - * ------------------------------------------------------------------- */* q- y) b. v$ [0 j2 T4 q8 W/ [
- uint32_t fftSize = 1024;
. g* S- x# i' R& U# [ - uint32_t ifftFlag = 0;
& F; }! Z% p; s3 H: H$ w. N j6 E - uint32_t doBitReverse = 1;" ^ a/ A; r: U& p ?
# d9 ^; t! u+ t/ h/ D- /* Reference index at which max energy of bin ocuurs */
$ }4 |' ^' e" m# y0 K6 M5 `2 B - uint32_t refIndex = 213, testIndex = 0;" I& f; o0 u6 B
# O2 O( @# j" C* M- /* ----------------------------------------------------------------------* \( _& K- l' z/ _# C
- * Max magnitude FFT Bin test
8 {$ A) E0 k# ], y2 e( w% h% q - * ------------------------------------------------------------------- */
) X6 r" W; U( f0 B& e4 o$ k2 v
7 c4 x) |1 ~! I4 P( Q, ]- int32_t main(void)
' ~/ C' M+ n& ?# i - {2 Z$ c2 F+ `# [
6 c6 Q0 ]* k v Q% q! p- arm_status status;8 I/ k5 s6 p9 `# H) i
- float32_t maxValue;! W( D6 F/ T- F7 v r9 b) f
- ) M$ E- u0 I0 c/ t
- status = ARM_MATH_SUCCESS;
* ]1 B5 f6 S4 U, |4 f1 L8 l4 F7 v: @. ?
6 t8 X+ {: e3 F2 L6 Z* h; d- //注意这个模块的参数的相关用法,下面这个将是我们后面进行调用的函数模块! b& b: u0 @3 U
- /* Process the data through the CFFT/CIFFT module */& W" l) O9 I$ M+ O
- arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32_10khz, ifftFlag, doBitReverse);
$ u3 g; `( q3 g3 x7 E; C4 | - //可以看到要想使用此函数,将调用4个参数- x5 k. {% Y% B( a
- //参数1:指向浮点CFFT结构的一个实例。两种:arm_cfft_sR_f32_len1024、arm_cfft_sR_q31_len1024;* `4 _) r. N5 s$ W' D' u# z
- //参数2:数据缓冲区的起始地址,偶数位为实数位,奇数位为复数( @3 M5 Y5 H& w1 C6 \4 A' m
- //参数3:是否逆FFT标志位;1-是
3 Q7 k; U) M \7 y& h4 z3 | - //参数4:是否位反转输出标志位;1-是4 ]8 D' s* x' F1 ]) K
- //注意:此函数将覆盖源数据,并将其修改为对应操作后的数据4 r5 M3 r, S& z/ V3 g
- `* h: a- Y2 C' y4 M& f: f- 4 T1 a. H) D5 J2 O
- //计算频域的幅度,由于对称性,只取前一半6 x. A, U4 E$ M, \+ L" L
- /* Process the data through the Complex Magnitude Module for# e) \% G) t5 y$ n- N
- calculating the magnitude at each bin */
9 j4 K7 |) a$ p9 c2 ~' V - arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);! c( q% B8 ~' F# F
- ( x: p8 @' N; L
- //计算频域的最大值
$ q9 q6 X9 a. t) B! W" a. c# \ - /* Calculates maxValue and returns corresponding BIN value */6 i8 u+ J9 D. H! ]3 O# Q/ E
- arm_max_f32(testOutput, fftSize, &maxValue, &testIndex); j* n; c/ o2 }2 W# v9 q3 z
- / n9 X6 `" j. U, e( M! S
- if (testIndex != refIndex)
$ M h$ K9 J0 f% G5 r - {
l0 j+ _+ u2 n - status = ARM_MATH_TEST_FAILURE;
4 A& B1 i6 n1 @% u8 g1 d3 [. }9 Z, \1 d - }
+ D& K5 o, ^& \/ E. d$ ~: k0 Z1 F
5 N* G$ n G3 q0 i% S- /* ----------------------------------------------------------------------
^, M" ]! L3 m' {( I - ** Loop here if the signals fail the PASS check./ @) Y4 ^( ]0 V. |
- ** This denotes a test failure4 A& A7 o% k7 U5 K
- ** ------------------------------------------------------------------- */1 C- K) g: @$ t5 O; q
7 h2 ?) o! r5 J; d: b; `- if ( status != ARM_MATH_SUCCESS)
" q! o) p1 T3 H0 ~ - {
& u6 r) l' h0 i' t - while (1);
?/ t) R3 F e% N. `! s& h7 I3 z - }
' u; |1 p; z% `6 n# H - / `# Y) d1 C5 M8 A4 \" }
- while (1); /* main function does not return */
3 P* b0 m: A* h- D - }
复制代码 $ _2 o7 V2 w) G- W2 ?! D
实际使用后的测试
9 ?& G' K+ {* c7 F3 o2 A6 l% `; J实际使用的时候,我们并不是使用对应的源代码c文件,而是使用对应的lib文件。
) G4 t0 U6 N7 @+ V: y; ]当我移植到工程中后,等下发布效果,不要在意上面如何能够运行,弄完后自己再实现。7 ~ T5 O5 b- N5 q
$ k( h3 B& W% \. T& G$ ~1 [
python处理源数据得到频谱0 Z' ^2 N7 U% D4 t
源数据有2048个数据,但实际是由实部和虚部组成的,所以实际只有1024个数据点* ?7 H6 m. ]2 N+ z2 I" [+ B$ O
8 F8 |6 L! L- D! G6 T+ x
# G" z+ a2 G r' H' P6 v; ]$ v
; _5 [5 }/ n7 ^
python会得到一部分负频率的成分,但是一般我们只讨论正频率部分2 F F" u( s$ r" W6 O" O, ~9 k% u
' ]2 V* q4 G. B8 C! L k( ^stm32处理源数据得到频谱
; ?) @0 ]4 P7 o- b) ]" u$ F% w! P. W这是stm32通过串口上传至电脑,然后用excel绘制的图像
" h0 R [9 V) {3 y) s) M
% n$ w$ b, m; d7 k. r6 f+ e1 F( V$ L; _( C# [; I2 g* h( a
8 h6 U; e1 G4 |# V两个结果一致
' }4 ?7 @4 T$ b5 H
; q3 w# i8 ~' ^! X( qFFT如何使用
. r/ s5 o8 a. E& }) o源数据------》调用相关函数-----》频域% c7 y8 j" ]% T( u$ z
频域中的各个点对应着相应的频率,幅值对应着当期成分的含量占比大小) _1 E6 q1 W, s4 d, b* q2 T
. ]7 E {9 J3 Scubemx的工程建立
1 R7 ~. l/ x) h1 }3 @$ b. V2 Z" n和普通的工程一样,不过建立之前需要注意勾选,复制所有文件到当前工程中;如果后面发现没有我们要的文件,可能是这一步的问题0 C# a6 [4 F) Q
* P7 {9 e. _3 N
2 N8 T$ X1 D1 P7 b4 C
' u8 r6 p. s5 o: w添加相应的库文件
1 J5 Z! D1 Y, H( q- a+ c先来查看工程文件夹中的一些文件
; ^ `. W+ E6 Z6 |, B$ j8 Y$ e
6 g, ^3 W0 B8 p: r+ x* i1 W/ k# X- F$ X5 U/ J% m& W
这里面的文件目录是:1 K9 P. ?; ], J. }# ?
工程文件夹\Drivers\CMSIS\Lib\ARM- I# Q( f. O2 c' C
里面就是我们所需的库文件* D b8 G/ [1 z$ @. d
$ C1 K7 ]) u/ d
下面添加到我们的工程中:
. ?& r+ x3 p: A0 H1 M3 d/ {
; s/ E T, ^) u; W5 W( M7 Z3 V/ i3 ]5 t: X4 o9 S V; R
; j, P* @) ~4 r' @* S0 R
然后设置添加文件的类型:
( \9 R1 ] `9 F
3 ]6 }9 S) W/ @& J
8 M1 C! O! m; |: e& j1 `6 @/ b
! W3 B* p/ B/ C" O' X3 \- V" N- P O选中小端模式的库,然后点击add,如果选错了,后面将不能编译,然后点击关闭窗口6 F" T( E" i- A4 t+ Q% I( s3 d, H* p. J
1 u: T9 D0 Z( }% L1 X% C
9 {, ]! s* q5 L3 f9 i" u
) g$ h# L! A* p& f
5 v' B$ X4 U$ l4 r3 @0 I1 q7 U$ R& s* Z) J9 [
Keil工程的设置
- s" Q0 [+ y- ^' b* Q& Y) A开启FPU并设置编译器:
) s; Z( _- o& p e将下面的东西复制到后面的图片中
+ }0 V' d+ ]2 {7 ?7 k' j8 R' M! V* j+ W4 r
- ,__FPU_PRESENT=1,__FPU_USED=1,ARM_MATH_CM7,__CC_ARM
复制代码
& Q% V8 `" Q' m' u6 R+ j# V" h然后添加一些文件% a: W3 l9 q$ G, k- I) p) q7 A
" q& t. H2 W* @* J$ |" w- c+ `0 a2 p9 `; w; }, d
) \2 I9 j) ?6 V9 `! t6 K/ }6 O" U! f
在这里输入
l" Q9 Z$ @' x…/Drivers/CMSIS/DSP/Include* I" d2 _+ }7 `% L7 l
5 e: { d1 I* t: C; ]* G9 S3 V
9 V0 Q" V5 X& h
O$ h# ~4 I$ _结果像这样) |1 B$ b& [3 ~
9 N9 D' ^( u' F# b+ S1 {* g) o. ~
( @5 G( T* b3 m% g4 _# t
然后点击ok
1 G7 L5 n, M' f9 K
8 l9 J5 P$ {: P# ?还要设置一个东东
9 t* p. c, U/ W( Y3 u! E( K
+ m/ ^/ F9 [- w4 w, J$ B6 Q
4 o r* [; ~+ c9 A! U- ~; M
+ _" ]0 u( F9 D" U* ], T( U3 _7 u3 E* K, F6 n, v( o9 y
这里使用的是STM32H750,所以后面提到的ARM_MATH_CM7后缀是M7
) C! B& @2 i; Z' g5 n; w
% {. d* J( u) t: l) ]现在就可以使用库里面的函数了1 Y# h* [& L1 |: ], v9 [0 A! g
& [& U- d8 F& ~# }
下面是测试$ w y A$ U/ @2 P, p. u& [& c) P
3 k& K, i5 J* z5 I1 j9 D8 f, e
进行FFT测试$ l, X7 h% f6 y6 E( |
测试一
$ e# }7 c5 v) }, F" W7 n% S9 N5 G- _添加测试文件$ D/ l. g4 H' ]' m2 O$ h/ y- d
使用的是官方测试文件
5 l9 S; \( `8 |: d2 k, I
M' |. R: m* f6 Z6 @9 {, |$ |2 i! @4 P" K$ D k) D* ~* B
4 Z5 ~2 z% t. I- \9 q1 o9 N( U
这是例程所在目录 \2 v& ]* W, T+ g/ G9 e [3 }
" Q1 L0 n4 d9 A( j9 _0 y. K+ w
9 z( \0 Z8 H- |. \& \3 z+ {2 E
- n/ g. z' w! s. n f. @2 W; `% e# a. O& i \
: V2 l9 ]+ S+ `" C% {5 e: ~
& e9 `! ~5 O* D1 Q4 E& z1 u8 B( {0 E
然后打开我们的main.c进行编辑
7 y+ H3 p6 J( B, [- A% N注意:
' u4 x. p) C* N t( w
# }2 U& T4 x6 m! M9 s. [6 d+ b我用的是uart4进行的串口通信3 A1 y+ L7 \' k b! E
3 b( u+ C+ r1 ?) Y
% ~1 R0 J3 m' V @
2 ?/ ^2 d! c6 Z5 z- ?
- P9 V3 y5 h8 {* }5 x( q% S- #include <stdio.h>
1 ?% f7 l+ i$ H4 Z0 f$ s - #include "arm_math.h"0 J1 |- W0 o- G1 E% M, y
- #include "arm_const_structs.h"$ j/ _1 o$ V# A# l
- - [0 l- M, _9 _8 J5 g
- #define TEST_LENGTH_SAMPLES 2048
2 S, V, c, {+ B: e3 ~+ h* a - 0 ^$ t- t- f5 u5 l% a, P
- extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];//only have 1024% e# `' I; s4 p0 Y' u6 ?
- static float32_t testOutput[TEST_LENGTH_SAMPLES/2];0 g, F' l( L, }0 a3 a
- uint32_t fftSize = 1024;, J" A/ Y* ^$ V
- uint32_t ifftFlag = 0;
% i# a" b" W. E# R - uint32_t doBitReverse = 1;$ L! O& `! k! N h3 q; H: D5 m) [
- 6 n' E3 b9 T2 G/ A" o
- /* Reference index at which max energy of bin ocuurs */
& q- ^2 y, d7 q. _2 j+ h; p. [! f - uint32_t refIndex = 213, testIndex = 0;
& i/ k4 C: C/ N* F5 D- B/ t - 1 F+ _6 Y8 g4 G2 j1 M2 [1 m0 K
. g& l0 g* R8 j3 N1 V2 s1 R- int fputc(int ch,FILE *f)
( ^4 ^ V# C. A' E - {
( P: A4 `( R6 S8 u! r - uint8_t temp[1]={ch};
9 s X, s$ Y" ~+ O0 | - HAL_UART_Transmit(&huart4,temp,1,2); //uart4 一定要修改为自己的串口!!!!!!!!!!!!
* n& v8 c3 J( r- Y4 v9 c9 ^ - }
复制代码 2 K5 m8 J' b/ T
然后
$ _5 B/ @! G# G7 x$ [0 G: I6 I5 P9 w% X$ \4 B/ V+ F
; v& p: r; y; U6 k0 h. G
9 ?- v1 U( `' T$ k- arm_status status;! n! `! i% g# ~$ O" _
- float32_t maxValue;' n/ D3 C# [ }8 W. M P/ `
6 J6 I; a0 R$ K7 n1 ]- status = ARM_MATH_SUCCESS;
9 h) J, k6 q( N q. a% p( ~
. Q2 s- L$ T: r- /* Process the data through the CFFT/CIFFT module */8 d$ `' K5 n! c, p! ]1 `6 ?
- arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32_10khz, ifftFlag, doBitReverse);
* t! R2 p) D Q# l6 A
. X9 i8 Z6 P5 [3 W4 k+ K/ h- /* Process the data through the Complex Magnitude Module for
! p- t' A# g: V& d. l - calculating the magnitude at each bin */
5 a* j" {' [& G; \ - arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);
2 m" o% K" ^" e" P
$ W6 c/ G( H( A |$ k0 s3 N- /* Calculates maxValue and returns corresponding BIN value */4 |! q( {9 [, I
- arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);& @% i, T9 I6 m3 a- V, g7 f$ A9 Y
6 v$ G( l, Z# t6 o- `! e- if (testIndex != refIndex)
7 U4 B4 o2 q+ y) C - {8 b* k* ~+ n& C5 G$ k! ?
- status = ARM_MATH_TEST_FAILURE;
- b; m) J/ {' `3 o1 D - }- x, @5 s7 `7 V3 s' n
6 Z" O" U3 J1 R3 y' R- /* ----------------------------------------------------------------------, w9 f) P0 e5 X( B$ f5 M
- ** Loop here if the signals fail the PASS check.; S; G x8 h8 m5 F- c. n
- ** This denotes a test failure! a/ \; N! d W3 _( p) O
- ** ------------------------------------------------------------------- */- v# Z' h6 C3 `( ] {% ~' \, j
5 I1 v4 c5 q" ~8 b- if ( status != ARM_MATH_SUCCESS)
; f5 _' J6 z. n8 g1 T - {
6 L; E0 [# }) t3 r/ V8 u* u - while (1);
7 |5 p: [' h0 j0 D, [( c - }
/ k9 o* r" D; y8 f/ {7 w - # B9 e7 V i( D8 t" z
- while (1)! [6 W- U/ C! c# W8 ?
- {
0 I7 q% S6 A# t5 K9 n! D1 Y9 S) } - //printf("hello\n"); " ~3 w) ?8 `' N3 j" K2 U
- HAL_Delay(5000);
: ]& V2 A- s& u! l% h - for(int i =0;i<1024;i++)
) I; l5 }: Z" v - {printf("%f\n",testOutput<i>);' o* O$ d- ?- m G1 N6 E
- </i>HAL_Delay(10);+ q$ s, Y$ ] l3 ^. p% h1 s6 x, V
- }
( A( p. D, E$ }, I& t! T6 P# ]+ d - while(1);$ P6 ? p; N+ V, G2 M9 ?$ p0 [3 m
- }
复制代码 3 P) d1 t# s& |' \1 n
这里完了就可以编译了
* O+ z7 L$ A! c* ^* |% H2 I4 T, ]/ N
5 ]" f* r% p4 k: X结果探究: v8 Y1 d0 |0 c; {& Q
打开串口助手,等待5s后会发送
! \/ Z# h# P/ C- u; } D* P# S7 W. E, j2 F( u: \
0 T; A) ]8 v1 B& E2 F* ^( n+ V, q
5 S4 S, G6 k9 h8 N3 Z& U. t: a0 s/ y: z5 p然后提取之后就是我们要的数据了,可以保存后用excel来进行绘制,就是我们上面的图像了
# O' P8 r# @: O9 z: F( n# I$ T2 V2 Q/ x: c1 R0 m/ e% H
; p& k7 h' O: J( n, v; K
|