STM32F407实现FFT,求频谱

前言

对于下文中提到的一些配置在我前面的文章找得到基于HAL库的STM32F4的 单通道ADC+DMA以及STM32F407如何通过CUBEMX添加DSP库,我想把我当初成功实验出来的能跑的FFT代码写出来,帮助大家能够用FFT去处理一些时域上处理不了的问题,能够去频域上处理。

区分时域和频域

时域:以时间为自变量,横轴是时间,纵轴是信号的变化
频域:以频率为自变量,横轴是时间,纵轴是频率信号的幅值,也就是我们说的频谱图

实现FFT

1、添加DSP库
STM32F407如何通过CUBEMX添加DSP库
2、代码

#define FFT_LENGTH 1024 
uint16_t adc_buff[FFT_LENGTH];//存放ADC采集的数据
float buf_Value[FFT_LENGTH] = {0};//ADC采样电压数组
float testInput[FFT_LENGTH*2] = {0};//FFT输入数组
float testOutput[FFT_LENGTH] = {0};//FFT输入数组

首先我们设置一个全局变量FFT_LENGTH 1024(这里也能设置成16,32,64,128,256,512,1024,2048,4096),这个长度看你自己决定。之后在定义FFT的输入数组testInput和输出数组长度testOutput。
傅里叶变换分为实部变换和虚部变换,在DSP中实部变换arm_cfft_fast_f32.c,虚部变换arm_cfft_f32.c,我使用的是虚部变换;我们需要将ADC采集到的数据放傅里叶变化的输入数组testInput中,虚部的存放方式是实部虚部交错排列的

我们调用
void arm_cfft_f32 ( const arm_cfft_instance_f32 * S,
float32_t * p1,
uint8_t ifftFlag,
uint8_t bitReverseFlag
)
arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput, 0, 1);//FFT变换

在这里插入图片描述
这里我发现这个博主写的很好,我就粘贴了他的一些东西,详情请查看STM32实现FFT,求取幅度频谱

	for(uint16_t i=0;i<FFT_LENGTH;i++)
	{
	  testInput[i*2]=adc_buff[i] * 3.3 / 4095;//实部
		testInput[i*2+1]=0;//虚部
	}
		arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput, 0, 1);//FFT变换
		arm_cmplx_mag_f32(testInput, testOutput, FFT_LENGTH);//求复数

我们进行1024点的FFT运算,testInput下标0需要除以FFT_LENGTH,其余的数除以FFT_LENGTH/2

		testOutput[0]/=FFT_LENGTH;//直流分量除以采样点数
		for(int i=1;i<FFT_LENGTH;i++)
		testOutput[i]/=FFT_LENGTH/2;//其他分量除以(采样点数/2)

最后再把结果打印出来

		for(int i=0;i<FFT_LENGTH;i++)
	  printf("%.4f\r\n",testOutput[i]);//打印数据

总的代码是:

结果

ADC采集以100K的频率去采集信号1Khz的正弦信号,信号2VPP,直流偏置1V

当然在一些情况,不需要直流分量,所以我们可以将直流分量置为0,testOutput[0]=0;//直流分量为0

FFT计算出的数据是对称的,我们只取前面一般的数组。
FFT输出数组的下标表示频率:频率=数组下标采样率/FFT采样点数*;数组下标0对应的是0HZ,就是直流偏置,幅值基本唯1,数组下标10对应的频率为:10×100k/1024=976HZ(近似);数组下标11对应的频率为:11×100k/1024=1075HZ(近似);1KHZ的信号落在了10和11之间,这引起了栅栏效应
如果我们将频率改成976HZ,2VPP的交流信号,1VPP的直流偏置,的时候

可以看到3根线一样长,很完美。

总结

我将我所写出来的FFT函数就这些了,函数能跑出来 且没有问题,但会有点栅栏效应,如果要减小栅栏效应,要么提高采样点数,将采样点数提高到4096个点,要么采样率降低,但是采样率降低的话采样一个高频的信号就无法采集。前面有两篇文件是配套的,可以一起参照着看。

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值