【STM32 系列】EXTI11触发三ADC同步(并非同步)采样 —— 超精准设置采样率
引言
前段时间测试 fft 计算频率的准确性时,发现用定时器触发 ADC 采样所设置的采样率在某些频率上十分的不准确,并且会产生非常严重的频谱泄露问题(具体可以看上一篇文章:频谱泄露原因)。
下面是我封装的一个设置定时器频率的函数:
点击查看代码
#include "set_samplingrate.h"
/**
* @brief 根据输入参数设置定时器以调整采样率
*
* 此函数依据给定的定时器时钟频率和期望的采样率,计算并设置定时器的自动重载寄存器值,
* 从而间接控制采样达到期望采样率。
*
* @param timerHandle 定时器句柄。
* @param Timer_ClockFreq 定时器的时钟频率。
* @param SamplingRate 期望的采样率。
* @return 返回期望设置的采样率。
*
* @note 函数依赖定时器句柄已正确初始化,且相关硬件寄存器和库函数正常工作。
*/
float32_t Set_SamplingRate(TIM_HandleTypeDef* htim, float32_t Timer_ClockFreq, float32_t SamplingRate)
{
// 声明变量用于存储定时器经过预分频后的频率
float32_t Timer_After_PSC_Freq;
Timer_After_PSC_Freq = Timer_ClockFreq / (float32_t)(htim->Init.Prescaler + 1);
// 计算并设置定时器的自动重载寄存器值,来调整ARR以达到期望采样率
__HAL_TIM_SET_AUTORELOAD(htim, (Timer_After_PSC_Freq / SamplingRate) - 1);
return SamplingRate;
}
点击查看代码
#ifndef __SET_SAMPLINGRATE_H
#define __SET_SAMPLINGRATE_H
#include "main.h"
extern float32_t Set_SamplingRate(TIM_HandleTypeDef* htim, float32_t Timer_ClockFreq, float32_t SamplingRate);
#endif
定时器触发误差来源
例如,博主使用的 H743 的 TIM3 的频率为200MHz,经过2分频后得到100MHz,在通过以上函数设置640kHz采样率,那么 CNT 的值就需要是156.25,但 CNT 的值只能是整形的156,那么最终得出的采样率值为$ \frac{100MHz}{156}=641025.64Hz $,这个看似微小的差异,其实可以造成极大的误差,此时就可以很清晰的看到频谱泄露带来的误差影响,甚至加窗后也解决不了:


EXTI11外部触发ADC采样
CubeMX配置
ADC1、2、3都是如此配置,假如你是H7系列的话,还需要注意时钟分频的问题,具体看这篇文章:H7时钟频率设置ADC


EXTI11测试结果
测试方式:使用信号发生器发生方波/脉冲给到 EXTI11 引脚,设置的方波/脉冲的频率就是采样率
1.使用640ksps采样率采样1024个点,采样5k倍数的正弦波/方波/三角波...加窗后并进行1024个点的 fft 运算。
-
采样5kHz正弦波:

-
采样100kHz方波:

2.使用32768sps采样率采样32768个点,采样任意频率的正弦波/方波/三角波...加窗后并进行32768个点的 fft 运算
-
采样4137Hz方波:

-
采样10109Hz正弦波:

可以看到,使用外部 EXTI 触发设置的采样率,计算的频率非常的准确,加窗后更是无敌,十分推荐使用。
隐藏问题
使用定时器可以同步触发三个 ADC 同时采样,在使用三个 ADC 同时采样一个信号的时候,算得的相位差的误差是相当的小,误差只有0.1%;但是使用 EXTI 触发采样时,三个ADC并不是同时触发的,使得就算采样同一个信号,算得的相位差误差也会较大,就是由于这个特性引起的,目前还没办法解决。也是各有所长,按需使用吧。
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/Skyrim-sssuuu/p/18783762

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X