衔接初阶内容,这一讲详细介绍下在实际项目应用中怎么运用。
用的还是那个最小系统板,网上十几块钱买的,引脚都有引出,方便跳线配接各种模块。
一、先介绍几点傅里叶变换的最基本知识
二、一说到采样就离不开单片机AD,下边介绍在STM32F1上利用DMA+TIM+ADC配置方式
1、打开CubeMX,新建工程,先配置时钟,如下:
无源晶振
选择外部8M晶振
2、配置DMA,如下
DMA1的通道1是ADC1
3、配置ADC通道,如下图
开了4个通道,独立的工作模式,使能连续采样,定时器3触发采样,板子上PC13连接了一个绿色LED,配置一下,工作时可以闪烁,方便观察。
4、定时器TIM3的配置
内部时钟,Counter Period按照采样频率进行计算。上文说过利用ST官方库函数进行256点的FFT,如果实现精度为1Hz的分辨率,那么采样频率就得是256Hz,对应周期就是1/256=3.90625ms,因此计数周期为3906。这个只是个计算方法,大家可以根据自己的实际需求选择合适自己的采样频率。
经过以上步骤,基础配置就完成了。生成工程文件,并打开编译,不能有错误。
三、按照上一篇所述方法,添加DSP库,这里不再重复。
四、AD采集的数据进行转换,注意一下,要想使用ST的库函数,就必须满足其数据格式,我没有找见说明文档,也是在别人帖子里边看到的。因为咱们采集的AD原始值就是需要进行FFT变换的,因此AD值就是函数的输入数据,而库函数的输入数据是32位数据,该数组中每个元素的高16位存储采样数据的实部,低16位存储采样数据的虚部(总是为0)。为什么要这样做呢?是因为后面要调用STM32的DSP库函数,需要传入的参数规定了必须是这样的数据格式。
1、数据处理,左移16位,既可以做到高16位是采样数据,为实部,低16位补0,为虚部。
调用的函数为void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
第一个参数为变换后输出数据,其格式为高16位是虚部,低16位是实部。第二个参数为需要变换的数据,即为模拟采样数据的数组。第三个参数为变换的点数。
2、采样一个周期为1s,也就是256个点。采集完成以后就可以计算了。然后按照上一篇提到的计算幅值方法进行计算,这里只计算了一个通道的数据。我是对库函数再次封装了,这里也挺简单的。
五、下面就来验证上述方法是否正确。
1、用信号发生器产生一个5Hz,幅值为1Vpp,偏移为1Vdc的正弦信号(单片机不能采集负电压,相当于0.5V到1.5V的一个信号)。见下图。
频率
幅值
实物连接
2、确认连接无误后,连接ST-Link进行仿真运行。打开Watch1窗口,查看数据是否正确。
可以看出输出数组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,上边换算的值偏高,问题就出来了。误差又变大了。
示波器测试的信号发生器信号
由上图可以看出,实际偏移量比信号发生器设置偏移量稍低,幅值比设置的偏大。
因此,实际偏移量=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,再次仿真。
幅值数据在输出数组中的第十个数据出现,验证无误。
到这一步,采样至FFT计算已经结束。
以上,仅代表个人观点,如有问题,烦请联系我指正。