前面是关于怎样运行fpu的,以及相关的环境配置" |1 n- `3 I3 n( z4 C
( h- k" C, j; t3 Y2 G$ QFFT的测试
- N( Y+ z9 K! C7 l! s9 b先看一段关于官方的FFT测试例程/ F6 J& K) [* c# C
里面添加了相关注释
- a0 R x; k- n
" N% P7 [. R$ ?. b' z& t- #include "arm_math.h"
4 y. A3 E& f6 ` X) x - #include "arm_const_structs.h"
8 r/ Z0 Q2 t2 |( o7 Z: B4 F - + N9 X9 p5 T# B8 L9 f' C
- #define TEST_LENGTH_SAMPLES 2048: @ e5 Y% }7 o O
- ; t2 c7 J+ n; [9 ?( Z# l }
- /* ------------------------------------------------------------------- V% `6 x q W% L0 Q; s
- * External Input and Output buffer Declarations for FFT Bin Example; F% v8 n4 z& Z
- * ------------------------------------------------------------------- */- O$ P7 X" ~9 v( C4 F) K! S! k
- extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];- J8 R9 P1 ? s7 Q+ n! D8 \
- static float32_t testOutput[TEST_LENGTH_SAMPLES/2];
. S$ r) i( S& c. ]4 J
: s/ Y: _+ W& }3 V4 h, a- /* ------------------------------------------------------------------# D d/ |) U+ w" M/ T% @
- * Global variables for FFT Bin Example, O7 \0 v/ A4 g" z- u: Q3 T
- * ------------------------------------------------------------------- *// } s( y3 v2 K$ d. ~/ A
- uint32_t fftSize = 1024;: M0 I( \$ Z$ A$ V
- uint32_t ifftFlag = 0;# s9 d. h7 p- ]2 d
- uint32_t doBitReverse = 1;- N# ^: I+ L( t4 Z/ H
, Y* g% n- _3 U) ^! }- v- /* Reference index at which max energy of bin ocuurs */6 U$ \; y5 B" A* N( j
- uint32_t refIndex = 213, testIndex = 0;
1 [' y9 i- ~* k$ X4 i9 U8 y3 K - 8 n8 G3 I; i& R* d
- /* ----------------------------------------------------------------------
2 L7 w- \& c9 o& P - * Max magnitude FFT Bin test
! h( y6 q# n$ z! Z6 i - * ------------------------------------------------------------------- */
) ?6 u9 Q7 C, F+ R. O
1 g, `! z+ h$ R; O- int32_t main(void)
+ c! P* C( v4 f- y3 W8 X - {2 X* o8 m4 z, O+ Y5 Q, ~
& K+ w& X$ }; M* d2 o; G5 I- arm_status status;
2 Z/ c+ B' b: Z( S! m4 M7 f1 k - float32_t maxValue;2 y! W. c/ E! h" ^9 p' J
! `. R" G9 r, B3 G. u& {. n5 \! P- status = ARM_MATH_SUCCESS;
' v0 [+ f$ q5 [4 A - " ]# S0 B7 a$ [ H# P' l
- //注意这个模块的参数的相关用法,下面这个将是我们后面进行调用的函数模块
* L: n$ g4 p9 _4 J# L3 U! y - /* Process the data through the CFFT/CIFFT module */6 n4 [; D8 L7 ?$ f
- arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32_10khz, ifftFlag, doBitReverse);
+ t% H7 H# Z: j5 g- B( ?+ I r1 l - //可以看到要想使用此函数,将调用4个参数
l0 d, [: z+ j$ @" a - //参数1:指向浮点CFFT结构的一个实例。两种:arm_cfft_sR_f32_len1024、arm_cfft_sR_q31_len1024;
+ l/ x2 p0 x+ d# h - //参数2:数据缓冲区的起始地址,偶数位为实数位,奇数位为复数
3 y! U! D/ [5 _" w) u( c - //参数3:是否逆FFT标志位;1-是
4 ?1 ]6 @: v- m4 y8 K - //参数4:是否位反转输出标志位;1-是
Z+ p" [* C2 t - //注意:此函数将覆盖源数据,并将其修改为对应操作后的数据
2 I$ L4 o4 N0 J: _- T - . S: W4 C9 O, y
9 V" g- F3 d4 b+ [4 f* M" q6 q- //计算频域的幅度,由于对称性,只取前一半
) F- D8 }3 E0 ~% w% {( |. ? - /* Process the data through the Complex Magnitude Module for
/ c1 d, l# T; i1 R- l+ N - calculating the magnitude at each bin */, ]3 j4 { `) B
- arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);1 @" w) I8 p: Y$ g/ ^2 S
- / I4 T7 N9 n8 }: h: {
- //计算频域的最大值
" U! p& v, k$ t8 p% x - /* Calculates maxValue and returns corresponding BIN value */
) Y9 K6 e: E6 t# D- x) Z - arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);" k$ ?) F7 ^' a0 j2 M( x
- ; F$ r9 M$ L7 y+ U
- if (testIndex != refIndex)
2 L5 \! P/ s+ T. o6 |) ? - {
0 _; t* g) E( w - status = ARM_MATH_TEST_FAILURE;
; @- \* d2 K0 M$ R - }- o! p8 u: O, _- H. }
- ) p2 g7 _5 ^, H. K! Q* d2 p
- /* ----------------------------------------------------------------------& q3 n s3 ]9 ~0 v( ]* ^5 C
- ** Loop here if the signals fail the PASS check.* [6 W, i: {# d2 n2 r
- ** This denotes a test failure0 L' {3 Q1 z# v9 ]) C7 n
- ** ------------------------------------------------------------------- */+ S' ?" G/ u# ~& g5 I5 d
- * ~( \1 S+ _6 Z) n
- if ( status != ARM_MATH_SUCCESS)5 N1 x& S* Q/ u' A9 X2 v
- {1 Z. E! A% V, W2 e
- while (1);7 E0 ]" p: p5 o
- }
2 S( e5 }% Y7 _2 | - " ^! t8 D3 W/ T0 N
- while (1); /* main function does not return */
0 c0 q8 u' |( m! H, ] - }
复制代码
: E9 R! [1 H/ g/ Q- H实际使用后的测试9 R6 M# y, [, @. ^1 K! I9 b+ K1 }
实际使用的时候,我们并不是使用对应的源代码c文件,而是使用对应的lib文件。. ?8 p) l$ l+ Y
当我移植到工程中后,等下发布效果,不要在意上面如何能够运行,弄完后自己再实现。
$ M8 Y/ p4 Y3 z& O
) j8 v( k' p) i9 Rpython处理源数据得到频谱
1 ?: d! ~8 M( }9 d1 X源数据有2048个数据,但实际是由实部和虚部组成的,所以实际只有1024个数据点4 C" q; z! M6 i3 w+ `. o0 I
+ o- P! \0 _+ j/ R5 H3 t( S
# U4 a7 ]. c+ [ P7 }* G' M, V$ K3 q' @8 h9 ]( F/ r
python会得到一部分负频率的成分,但是一般我们只讨论正频率部分: H' y, t+ C/ A
+ g1 M1 E4 ~, Z& Q2 N! n7 mstm32处理源数据得到频谱
, `0 J5 T. t+ {6 ?$ z这是stm32通过串口上传至电脑,然后用excel绘制的图像
: l" }+ B' r7 Y0 T+ Z( w
6 P `$ }- q$ o4 l: |& D! W" H6 `2 F4 ]8 H2 b m6 T
g% c k/ \8 V4 H7 h- |" q8 F两个结果一致0 o4 ^# x- a. S$ m$ @
# y1 Z3 ]# A4 g2 z* J
FFT如何使用: \6 W7 o- M( o: C- S% q0 s4 q
源数据------》调用相关函数-----》频域* T! T' L, }, g: Y
频域中的各个点对应着相应的频率,幅值对应着当期成分的含量占比大小# A$ ?8 b, d- E# E& @+ ?& X3 l
5 r6 ~- D! V4 k8 l% q4 p
cubemx的工程建立
% l3 |- u$ o$ a: t: o和普通的工程一样,不过建立之前需要注意勾选,复制所有文件到当前工程中;如果后面发现没有我们要的文件,可能是这一步的问题
. ]8 a; w! C4 [; I% [2 D+ U" L" F7 l! x3 T$ K; |
# }8 u* H5 @8 j2 h" R. ]& W
' q2 W) T* S5 M! m4 d1 r3 ~# R4 E添加相应的库文件
% d; Z) Y5 L+ V r) e+ v2 ^先来查看工程文件夹中的一些文件4 l" z# B( C- ?3 m" C9 ^4 a# m- `, W
. M. v3 [( K' I) k* j- D7 J
1 i* C& Y# j/ ~) g" Q+ D. h
这里面的文件目录是:
6 ]1 m8 a1 q- ^/ T' N4 R7 J工程文件夹\Drivers\CMSIS\Lib\ARM
$ u e/ {0 G& o; p6 g1 o+ e里面就是我们所需的库文件
9 r& F2 i) ]+ Y+ F1 j' _) v
6 t" c% s7 ~/ C下面添加到我们的工程中:
+ f0 J q, \ ^
( `9 q1 n4 p; D) {0 w( T p
|/ s# q6 u' A" e9 v) |0 g2 E4 O6 Y3 I2 L2 d1 ]3 c9 M
然后设置添加文件的类型:
1 _+ `* u- h% K3 r
3 @' x8 l, N8 M/ j' D B- A7 I, C: F9 r0 E* m9 Q2 I: S+ ]
4 `1 G* U$ D) S% x4 I
选中小端模式的库,然后点击add,如果选错了,后面将不能编译,然后点击关闭窗口. Q$ G- Z3 x4 z9 K( [
# f3 P- ?4 k# D" t( e% B! q( ^: f0 i
T( P. X8 a+ A0 e# [9 l: G6 @# B0 @9 D8 M, V, U
|/ j: r( R- f) N/ N5 C$ g
/ M) D+ J$ g8 X6 n8 s# dKeil工程的设置
5 u- D% Q9 y1 J# O' V开启FPU并设置编译器:! O' b5 a8 h1 k e" G
将下面的东西复制到后面的图片中# p! N. s* G" G# S' L3 Q+ W
: y+ s I4 [5 l; R2 d L) K- ,__FPU_PRESENT=1,__FPU_USED=1,ARM_MATH_CM7,__CC_ARM
复制代码
$ a0 a! | a; i2 A然后添加一些文件
: i: {9 I5 W9 B. Z* i1 S |
+ b! a) u6 E7 j+ }/ T4 Z0 W& D- R* K; p7 t6 {7 ^ [
6 k! |3 m- s" |: u% M) O* S
在这里输入
! Q/ K4 l3 u9 a2 J7 I…/Drivers/CMSIS/DSP/Include
+ `. @# x5 g" x
1 [* g% p: J$ R# t( S( q) B' G2 {+ {4 j% y0 s
- g! j: h' p' q2 d" K1 s" D" E7 ^结果像这样
; G# y; [" T- x( q% p1 [2 S) S) _' j+ g7 n
: L; O2 s: {* R+ o4 `- @: I
然后点击ok& z- |0 `& Y/ x- l! y3 `3 C: g) d
, s) [8 u" R0 A& W2 E
还要设置一个东东
+ _7 H, C0 h- I: c" s
3 Q2 S" Y \. A& }& W8 d& o I0 r" D3 r' i) u8 V V- u3 B
) S6 E5 k& I u( S" ^( }% z# c( B: T$ z8 \0 k
这里使用的是STM32H750,所以后面提到的ARM_MATH_CM7后缀是M7, S! p) j! v' W5 K! u# @) I# _
; }4 U) d1 D+ C- p$ v3 h. ?
现在就可以使用库里面的函数了6 O5 v( ^% e2 m+ O# G8 ~2 z, L
$ ]6 T/ ~' H4 C# s v
下面是测试( p& m, t3 C4 Z1 Z; e9 I
& N: r0 h6 O9 H6 l" X; G I进行FFT测试
0 L) ^& m: ~4 b# X) |测试一2 z) F. ^+ O0 T! P
添加测试文件
; X5 {: u$ {2 d: W使用的是官方测试文件# K! H1 V: C2 Z# t* l% p' e. S
& O* s; U/ Z( v* D* R# r
, B0 i" M9 y# Z3 W. Q) p3 o3 ^0 g: [# I0 E$ v8 E
这是例程所在目录
1 }; M! V7 D: b9 A0 O5 d6 G2 e! M l2 d, v' t% U, K* ]
, M# {7 K, K0 O- j6 I( b2 F* c y7 S5 A. T! N, u; ^
# ^& j0 p* e2 z6 h$ |
& i* {& K6 n2 \. a5 j7 R8 ?: c
" | Q; g! l! c! B& a& e4 `7 v9 {: g
) e* N! x, D- K. J8 F. d2 B然后打开我们的main.c进行编辑
! J; m1 \9 {: e% _注意:$ i7 |% ^, j% T
( Y$ Z" i* Y8 M% O$ u
我用的是uart4进行的串口通信
3 B& @3 N4 Z& `5 g1 P
% s* n# D7 X! G2 k! [" \
, o6 y$ z8 J* S5 ?) _) q- A2 b) z- h; z @0 |" Y# e. w7 X
* }* B+ b& R3 i- #include <stdio.h>
0 W% X/ N6 _' y* ^5 s0 x8 F - #include "arm_math.h"8 I- X9 S$ u8 l
- #include "arm_const_structs.h"% H: {- m, m) e2 D: c
! C) M- E. U6 B! l* w& l6 q- #define TEST_LENGTH_SAMPLES 2048
- U" y5 p& L( [# i
; C" t7 J- C F P- extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];//only have 1024
5 }/ x! \( T. ?4 v - static float32_t testOutput[TEST_LENGTH_SAMPLES/2];$ e2 ^! R: r5 ~1 d
- uint32_t fftSize = 1024;: G% [! U: q& M! o
- uint32_t ifftFlag = 0;
: s! M3 m, ^; ?: ` - uint32_t doBitReverse = 1;
3 r% h7 b& v2 H0 \& R) ?" ~ - 2 e# |5 k( q) T* Y
- /* Reference index at which max energy of bin ocuurs */
; q+ T" a# o2 d: A, Z - uint32_t refIndex = 213, testIndex = 0;
0 w# ]& n/ m' f - ' \; ^3 k$ n& J
- % Y1 s* k! H: y4 B3 C8 d9 Y, z
- int fputc(int ch,FILE *f)
% O5 I. V6 Y& W& H- p - {
% e1 ^; E! d9 \; } - uint8_t temp[1]={ch};& I: l4 c$ t* Q4 a4 Y
- HAL_UART_Transmit(&huart4,temp,1,2); //uart4 一定要修改为自己的串口!!!!!!!!!!!!$ S7 Y; m8 i- h9 {, r1 r
- }
复制代码
( Z+ d2 `% ]0 s7 z# A. w然后5 w. f. s; A3 H
0 u. J- N9 k! W$ f
7 g* ^8 E4 }+ i; u8 _9 l! N ^% Q- & [, u# d$ e5 N# A& D p
- arm_status status; P7 p, h9 L) N0 o
- float32_t maxValue;
% ~7 @6 m9 v4 Q N* o - 2 ~. r0 d/ ?4 N" m/ k
- status = ARM_MATH_SUCCESS;) p" Z( F2 u/ p* t8 y" `
- / u9 k2 `1 O) z) O5 y/ J, J' e
- /* Process the data through the CFFT/CIFFT module */
" D" t* C7 F+ g6 `' B& _6 M" B( C - arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32_10khz, ifftFlag, doBitReverse);4 h$ F7 m8 ?4 W N
: J& @ I; A/ V4 c* \! }$ [; E- r6 C- /* Process the data through the Complex Magnitude Module for* b5 N2 T' N7 ]! m& J# @# F! z
- calculating the magnitude at each bin */8 m$ a) c- K+ I J5 I; L/ C
- arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);
% D; K: x# U* P& `4 y5 y. F
& b# B% `- Q2 h* n& R$ k. D- /* Calculates maxValue and returns corresponding BIN value */6 x ~# C0 q$ v: G4 I- f
- arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);" X; E. F/ o8 e' U9 H
- 7 h$ d5 O& p+ Q: z+ ~$ M
- if (testIndex != refIndex) D& h1 B/ v# H7 f9 x, U# z+ H
- {; k( K+ A( c$ @. a( W D
- status = ARM_MATH_TEST_FAILURE; U5 F0 |6 ~* Z! Z V0 J
- }9 ?+ H' g- Z: S+ j2 K0 A
- + k- W2 e a. T& l }" @
- /* ----------------------------------------------------------------------
2 r2 F1 w' {) v+ a- n9 P, h& z - ** Loop here if the signals fail the PASS check.1 P6 \- `$ Y- {$ p9 q2 Y) X- }
- ** This denotes a test failure, X4 V0 i6 p8 l# ~8 a7 f6 i# {+ Z
- ** ------------------------------------------------------------------- */
4 X- \$ K. `7 e( U
5 K6 x+ v3 r+ H& n- if ( status != ARM_MATH_SUCCESS): u1 R- Z! Z& J2 h9 M5 F, J
- {; x) n5 {9 z: w9 v
- while (1);2 @" O( |9 L! F( I
- }
/ h4 W7 ` A+ H. c2 u/ z, g1 @
6 Q' N- y! {3 Z% x- while (1)
# O+ q+ Z+ Z2 [# q - {
6 f9 P3 g2 l- A+ ` - //printf("hello\n");
0 o( ~( P' H; Y3 M, W6 S6 j$ Y - HAL_Delay(5000);
) ^) C( g# z5 x9 R" m/ q5 | - for(int i =0;i<1024;i++)" M- q" @2 i& h+ R* L/ H
- {printf("%f\n",testOutput<i>);- a$ ]9 |* v! e! p
- </i>HAL_Delay(10);
b" m4 Z% ?6 E# l1 e7 ]: k - }7 u& z2 P- b$ c H) \, {
- while(1);. E6 t7 }6 [3 y5 Y& t
- }
复制代码
# k# D' F" ?* X1 d! Y/ @- V8 y这里完了就可以编译了
]# c, {0 Z0 \% D( F
2 [- o* D: ?! _2 Q, |* R5 k结果探究
% s. q! Z' a, M# j4 {( u- v- I ]/ d打开串口助手,等待5s后会发送
3 V8 G& }) Q! P. h! |1 ~
* P. T* m. G0 C ^* g0 Z
; u/ t! d. \! o6 w& ~0 C) v4 Z: V" G
然后提取之后就是我们要的数据了,可以保存后用excel来进行绘制,就是我们上面的图像了
! J6 l& z: p9 Y" ^$ O5 v# [" ~( \' W# Z, C
: `" m. |6 H. ]* q+ |9 U3 @( h
|