STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶

衔接初阶内容,这一讲详细介绍下在实际项目应用中怎么运用。

用的还是那个最小系统板,网上十几块钱买的,引脚都有引出,方便跳线配接各种模块。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第1张图片

 一、先介绍几点傅里叶变换的最基本知识

  1. 采样定理:又叫奈奎斯特定理,采样频率fs要不小于信号最高频率fH的两倍,最后就能无失真的恢复原信号。例如,采样100Hz的信号,那么采样频率就不能低于200Hz。
  2. 采样周期、采样频率、采样点数、精度(频率分辨率)之间的关系。周期和频率之间的关系就不说了。采样点数和咱们调用的库函数有关,ST官方已经写好了基2或基4的函数,如果是基2的,采样点数必须为2的整数次方。如果是基4的,采样点数必须为4的整数次方。STM32F1系列单片机的DSP库为基4的,而且库函数中只包含64点,256点,1024点这三种。本篇介绍256点的FFT变换。精度受采样频率和采样点数共同决定,精度=采样频率/采样点数。

 二、一说到采样就离不开单片机AD,下边介绍在STM32F1上利用DMA+TIM+ADC配置方式

1、打开CubeMX,新建工程,先配置时钟,如下:

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第2张图片

 无源晶振

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第3张图片

选择外部8M晶振 

2、配置DMA,如下

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第4张图片

 DMA1的通道1是ADC1

3、配置ADC通道,如下图

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第5张图片

 开了4个通道,独立的工作模式,使能连续采样,定时器3触发采样,板子上PC13连接了一个绿色LED,配置一下,工作时可以闪烁,方便观察。

4、定时器TIM3的配置 

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第6张图片

 内部时钟,Counter Period按照采样频率进行计算。上文说过利用ST官方库函数进行256点的FFT,如果实现精度为1Hz的分辨率,那么采样频率就得是256Hz,对应周期就是1/256=3.90625ms,因此计数周期为3906。这个只是个计算方法,大家可以根据自己的实际需求选择合适自己的采样频率。

经过以上步骤,基础配置就完成了。生成工程文件,并打开编译,不能有错误。

三、按照上一篇所述方法,添加DSP库,这里不再重复。

四、AD采集的数据进行转换,注意一下,要想使用ST的库函数,就必须满足其数据格式,我没有找见说明文档,也是在别人帖子里边看到的。因为咱们采集的AD原始值就是需要进行FFT变换的,因此AD值就是函数的输入数据,而库函数的输入数据是32位数据,该数组中每个元素的高16位存储采样数据的实部,低16位存储采样数据的虚部(总是为0)。为什么要这样做呢?是因为后面要调用STM32的DSP库函数,需要传入的参数规定了必须是这样的数据格式。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第7张图片

1、数据处理,左移16位,既可以做到高16位是采样数据,为实部,低16位补0,为虚部。

调用的函数为void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);

第一个参数为变换后输出数据,其格式为高16位是虚部,低16位是实部。第二个参数为需要变换的数据,即为模拟采样数据的数组。第三个参数为变换的点数。

2、采样一个周期为1s,也就是256个点。采集完成以后就可以计算了。然后按照上一篇提到的计算幅值方法进行计算,这里只计算了一个通道的数据。我是对库函数再次封装了,这里也挺简单的。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第8张图片

  五、下面就来验证上述方法是否正确。

1、用信号发生器产生一个5Hz,幅值为1Vpp,偏移为1Vdc的正弦信号(单片机不能采集负电压,相当于0.5V到1.5V的一个信号)。见下图。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第9张图片

频率

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第10张图片

幅值

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第11张图片偏移量 

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第12张图片

 实物连接

2、确认连接无误后,连接ST-Link进行仿真运行。打开Watch1窗口,查看数据是否正确。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第13张图片

可以看出输出数组fftout[0]为1224,第一个数据为直流分量,即一个周期内数据的平均值,对于正弦波来说,平均值就是偏移量,1224/4095*3.3=0.986V,相差0.014V。

fftout[5]数据为669,首先可以判定频率数据是正确的,输出数组每两个数据的间隔就是频率分辨率(精度),fftout[5]就代表频率为5Hz的数据。将其转化为电压值669/4095*3.3=0.539V,约为0.54V。代表5Hz处的幅值。

以上计算的数据是否正确呢,首先看偏移量,应该是1V才对,信号发生器设置的就是1Vdc,相差了14个mv。5Hz处数据的幅值应该是0.5V才对,因为信号发生器设置的是峰峰值1V,相差40mV。感觉因误差造成的计算偏差还在合理范围内。但是又觉得哪里不对,于是用示波器测了一下信号发生器的信号,用万用表测了一下单片机的3.3V,实际值只有3.27V,上边换算的值偏高,问题就出来了。误差又变大了。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第14张图片

 示波器测试的信号发生器信号

由上图可以看出,实际偏移量比信号发生器设置偏移量稍低,幅值比设置的偏大。

因此,实际偏移量=1.5-1.1/2=0.95V。而幅值=1.1/2=0.55V。

理论计算,偏移量=1224/4095*3.27=0.977V,幅值=665/4095*3.27=0.531V。

不论怎么计算,计算总有误差,不可能保持理论值和实际值一样。

再次验证频率,将信号发生器信号频率调节到10Hz,再次仿真。

STM32F1系列单片机如何用官方提供的DSP库进行FFT-进阶_第15张图片

 幅值数据在输出数组中的第十个数据出现,验证无误。

到这一步,采样至FFT计算已经结束。

以上,仅代表个人观点,如有问题,烦请联系我指正。

你可能感兴趣的:(单片机,stm32,嵌入式硬件)