1.前言
三天前的积分赛需要用到fft来测量信号的频谱,于是乎在网上找找教程。发现之前已经有学长分享过经验,但是自己跟着添加的过程中还是遇到了一些keil里面的报错,在网上又找了找相关文章,最后终于是解决了问题,并且在校初选中运用fft测量了信号的频谱,于是想写下这篇文章当作备忘。贴下学长的帖子的链接:https://blog.csdn.net/qq_34022877/article/details/123190943
2.cubemx配置
在cubemxpack里面选择dsp库,若没有下载还需要先下载,然后打对勾
cubemx左侧拉到最下面点开middware 选择x-cube-algobuild,勾选dsp
接下来按照正常配置就行
3.keil配置
点开环境管理
在cmsis里选中dsp
点击魔术棒,在c/c++里添加宏定义
这里需要添加的内容是:arm_math_cm4,这里的cm4是因为g431是m4的,如果是其他需要更该相应的数字
这里添加忽略警告
--diag_suppress=2803,1,1035
将cubemx生成的这个路径删除,不然编译的时候会重复引用报错,这里需要注意每次cubemx生成的时候都会自动添加到这个路径,在使用cubemx生成后这里记得要删除
接着引用头文件并定义fpu
#define __fpu_present 1u #include "arm_math.h" #include "arm_const_structs.h"
如果使用了printf等函数需要包含头文件stdio 并且需要勾选use microlib(这个界面在魔术棒 target栏里)
最后点击编译,发现零错误零警告,大功告成
4.部分代码
内容部分基本和前面贴的学长的帖子里基本一致,这里写一下我的数据处理部分,作抛砖引玉,希望能和大家交流,互相学习。
int j;
int frequence[3]={0};//定义存储频率的数组
float amplitude[3]={0};//定义存储幅值的数组float类型
printf("%.2f\n",fft_outputbuf[0]);//串口调试用
frequence[0]=0;//直流频率
amplitude[0]=fft_outputbuf[0];//直流分量
for(j=0;j<512;j++)//之前存储了1024个点,但只有512有效
{
if(fft_outputbuf[j]>1)//这里fft_outputbuff里面存放的是峰峰值,这里是为了找到基波,由于输入信号的峰峰值是1v到2v 的方波,傅里叶变化后得到的基波是方波峰峰值乘4/pi,也就是说基波的峰峰值一定大于1v,只要找到第一个大于1v就是基波
{
printf("%d:\t%.2f\r\n", j, fft_outputbuf[j]); //串口调试
frequence[1]=j*5;//基波频率 (这里配置的cubemx时钟频率170mhz 定时器设置的arr是33203 采样率 = 170000000/33203 = 5120,fft计算点数为1024 这里配置采样率5120是为了让频率最小变化5hz 频率等于数组下标*采样率/fft计算点数)
for(c=0;c<10;c++)
{
fft_tem += fft_outputbuf[j+c-10]*fft_outputbuf[j+c-10];//由于栅格效应,将周围50hz频率的点都平方相加
}
amplitude[1]=sqrt(fft_tem);//这里开根号
fft_tem =0;
frequence[2]=j*5*3;//3次谐波直接基波频率*3
for(c=0;c<10;c++)
{
fft_tem += fft_outputbuf[j*3+c-10]*fft_outputbuf[j*3+c-10];//3次谐波周围的数据处理
}
amplitude[2]=sqrt(fft_tem);
fft_tem =0;
}
}
sprintf(str_buff[0],"fou_vpp=%.2fv",amplitude[1]-0.1);
sprintf(str_buff[1],"fou_fre=%dhz",frequence[1]);
sprintf(str_buff[2],"thr_vpp=%.2fv",amplitude[2]-0.1);
sprintf(str_buff[3],"thr_fre=%dhz",frequence[2]);
oled_clear();
oled_showstring(0,0,str_buff[0],16, 0);
oled_showstring(0,2,str_buff[1],16, 0);
oled_showstring(0,4,str_buff[2],16, 0);
oled_showstring(0,6,str_buff[3],16, 0);//oled显示信息
最后fft部分误差处于误差范围内。
4.18号更新,最近再用的时候发现如果两次编译器版本不一样就会出现__fpu_present unknown的错误,目前还没有找到问题的原因和解决问题的方法,建议最好从头开始都不要更换编译器版本
发表评论