|
爱科技、爱创意、爱折腾、爱极致,我们都是技术控
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 inthsunshine 于 2024-2-23 19:49 编辑
其实教程网上都有,结合我自己的实践,尽量简化写一下
首先芯片要带硬件浮点FPU,也就是M4核心或者M7核心,STM32F3,F4,F7,H7,F2,H5...等等这些都可以
然后在keil mdk上开启FPU, 可以修改宏定义_FPU_USED=1,更简单的办法是在mdk菜单里开启,点击魔术棒图标(Options forTarget…)里的"Target"选项卡,右边的"Code Generation"下的“Floating Point Hardware”下拉菜单可以开启(一般是单精度,M7核心的型号支持双精度)
程序上需要包含头文件
#include "arm_math.h"
添加DSP库文件arm_cortexM4lf_math.lib(M4核心, M7核心就加对应的库文件)到工程里
至此准备工作已完成,接下来是怎么调用dsp库的函数
在头文件里宏定义采样点数量
#define NPT 512
先定义一个实例
arm_rfft_fast_instance_f32 S1;
然后对其初始化
arm_rfft_fast_init_f32(&S1,NPT);
一般我们是用ADC的结果或者从tf里读取数据做FFT运算,所以我们调用实数FFT函数就行
当然,需要先定义存放数据的数组
float FFTin[NPT], FFTout[NPT], FFTmag[NPT/2]; //放在C文件的前面
其中FFTin是输入数据,NPT个采样点
FFTout是运算后的输出数据,因为实数FFT后变成复数,每个频点按实部,虚部顺序存放,占用2个元素,但后一半是空的,函数不计算减少计算量(频谱对称),数组长度还是NPT
如果采样频率是fs,采样点数NPT, 那么频率分辨率则是fs/NPT, 所以FFTout的频率是从0(直流分量)开始,fs/NPT, 2*fs/NPT,一直到(NPT/2-1)*fs/NPT, 一共NPT/2个频点。
FFTmag存放FFT结果的模值(实部和虚部平方和的开方),因为FFT结果是对称的,有用的数据只要取前半部就可以,它的长度是NPT/2
调用实数FFT函数
arm_rfft_fast_f32(&S1,FFTin,FFTout,0); //参数表的最后一个0,指执行傅里叶正变换,逆变换是1
计算各频点的模值,
arm_cmplx_mag_f32(FFTout,FFTmag,NPT);
至此FFTmag存放各频点的模值,也就是幅度值,如果需要相位值(初相),也可以计算,就是arctan(虚部/实部)
不过此时的幅度值,和输入信号的频率分量并不对应,需要再转换,具体是
如果频率=0(直流成分), 幅值需要除以NPT, 其它频率需要除以NPT/2
这样计算出来就是输入信号对应频率的振幅,保持一致,之后可以用来分析或者显示,就根据自己需要了
当然为了验证运算的正确性,可以简单编写一个测试小程序,输入数据就用计算方法得到,然后执行FFT,再根据最后计算结果和输入信号对比,正确说明ok
for (j=0;j<NPT;j++)
{FFTin[j]=500+1000*arm_sin_f32(2*PI*50/2560*j+2*PI*30/360)+2000*arm_sin_f32(2*PI*200/2560*j+2*PI*78/360);} //构建一个包含直流的多个单频信号的组合信号
arm_rfft_fast_f32(&S1,FFTin,FFTout,0);
arm_cmplx_mag_f32(FFTout,FFTmag,NPT);
for (j=1;j<NPT/2;j++)
{FFTmag[j]/=(float)(NPT/2);}
FFTmag[0]/=(float)NPT;
我们构建的函数是f=500+1000sin(2π*50*t+30°)+2000sin(2π*200*t+78°),频率分别是50Hz和200Hz
采样频率2560Hz, NPT=512, 频率分辨率=2560/512=5Hz, 也就是频率间距为5Hz,运算结果
FFTmag[0]就是直流成分,50Hz对应FFTmag[10], 200Hz对应FFTmag[40], 计算结果和输入信号基本一致。
最后放一个tf卡的音频频谱显示demo视频:
PS: 奇怪我电脑放不出下面的视频,链接在这里 https://www.bilibili.com/video/BV1Ly421872U/
STM32的频谱显示DEMO.mp4
(6.63 MB, 下载次数: 0)
|
打赏
-
查看全部打赏
|