一、输入捕获测频原理简述
STM32定时器输入捕获模式通过检测信号边沿,将当前计数器值锁存到捕获寄存器,结合两次捕获值和时间基准计算频率。常用方法有:
- 直接测频法:固定闸门时间,统计脉冲个数。
- 测周法:测量相邻同向边沿间的时间间隔,取倒数得频率。
本文以测周法为例,分析预分频(PSC)与捕获边沿(上升沿/下降沿)配置带来的误差。
二、误差来源分析
2.1 预分频引入的量化误差
定时器计数频率 fCK_CNT = fCK_PSC / (PSC+1)。捕获值 CCR 的分辨率为一个计数周期 Tcnt = 1/fCK_CNT。测周法频率计算:
freq = fCK_CNT / (CCR2 - CCR1);
-
量化误差:
Δf/f ≈ 1/(CCR2-CCR1)。预分频越大,fCK_CNT越低,相同信号周期内计数值越小,量化误差越大。 - 预分频相位不确定性:PSC 计数器与信号边沿异步,每次捕获时 PSC 相位随机,导致捕获值存在 ±1 个计数周期的抖动。
2.2 捕获边沿配置的误差
- 边沿抖动:信号上升/下降沿非理想,存在噪声或振铃,可能触发多次捕获。
- 边沿不对称:若信号占空比非 50%,上升沿与下降沿间隔不等,用不同边沿测周会引入系统误差。
- 输入滤波器延迟:配置了输入滤波(ICF)会引入固定延迟,影响高频测量。
2.3 其他误差
- 时钟源精度(HSI 偏差可达 ±1%)。
- 中断响应延迟(若用中断读取 CCR)。
- 计数器溢出处理不当。
三、配置步骤与代码示例
3.1 硬件设计
- 信号接入 TIMx_CH1(如 PA0)。
- 使用外部晶振(HSE)作为时钟源,提高基准精度。
3.2 定时器配置(以 TIM2 为例)
void TIM2_Capture_Init(void)
{
// 1. 时钟使能
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 2. GPIO 配置为复用功能
GPIOA->MODER &= ~(3U << (0 * 2));
GPIOA->MODER |= (2U << (0 * 2)); // AF mode
GPIOA->AFR[0] |= (1U << (0 * 4)); // AF1 = TIM2_CH1
// 3. 时基配置:预分频尽量小,提高分辨率
TIM2->PSC = 0; // 不分频,fCK_CNT = 84MHz(假设APB1=84MHz)
TIM2->ARR = 0xFFFF; // 最大自动重装
// 4. 输入捕获配置:上升沿,无滤波,无预分频
TIM2->CCMR1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1PSC | TIM_CCMR1_IC1F);
TIM2->CCMR1 |= (1U << 0); // CC1S=01,IC1映射到TI1
TIM2->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); // 上升沿捕获
TIM2->CCER |= TIM_CCER_CC1E; // 使能捕获
// 5. 使能捕获中断
TIM2->DIER |= TIM_DIER_CC1IE;
NVIC_EnableIRQ(TIM2_IRQn);
// 6. 启动定时器
TIM2->CR1 |= TIM_CR1_CEN;
}
3.3 中断服务与频率计算
volatile uint32_t cap1 = 0, cap2 = 0;
volatile uint8_t flag = 0;
volatile float freq = 0.0f;
void TIM2_IRQHandler(void)
{
if (TIM2->SR & TIM_SR_CC1IF) {
TIM2->SR &= ~TIM_SR_CC1IF;
if (flag == 0) {
cap1 = TIM2->CCR1;
flag = 1;
} else {
cap2 = TIM2->CCR1;
uint32_t diff = (cap2 > cap1) ? (cap2 - cap1) : (0x10000 + cap2 - cap1);
if (diff > 0) {
freq = 84000000.0f / diff; // fCK_CNT = 84MHz
}
flag = 0;
}
}
}
四、校准方法
4.1 硬件校准
- 使用高精度时钟源:外部晶振(如 8MHz ±10ppm)替代 HSI。
- 信号调理:加施密特触发器或低通滤波,消除边沿抖动。
- 匹配阻抗:减少反射引起的振铃。
4.2 软件校准
- 多次测量取平均:连续测量 N 次,剔除异常值后平均。
- 动态调整预分频:根据信号频率范围自动选择 PSC,使计数值在 1000~60000 之间,平衡分辨率与溢出。
- 边沿一致性校验:交替捕获上升沿和下降沿,比较周期差异,判断占空比影响。
- 补偿固定延迟:通过已知频率信号标定,计算并扣除滤波/中断延迟。
4.3 校准代码示例
#define N 10
float measure_freq_avg(void)
{
float sum = 0;
for (int i = 0; i < N; i++) {
flag = 0;
while (flag == 0); // 等待一次完整捕获
sum += freq;
}
return sum / N;
}
五、注意事项
- 预分频不宜过大:在满足量程前提下,PSC 越小,分辨率越高。
- 捕获边沿选择:优先使用信号质量较好的边沿;若占空比未知,可配置双边沿捕获并计算平均周期。
- 防止计数器溢出:测周法需处理 ARR 溢出,建议使能溢出中断并扩展计数。
- 输入滤波配置:高频信号慎用 ICF,避免引入额外延迟;低频信号可适当开启以抑制噪声。
- 中断优先级:捕获中断应设为较高优先级,减少响应延迟。
通过合理配置预分频与捕获边沿,并结合软硬件校准,可将测频误差控制在 0.1% 以内,满足大多数嵌入式应用需求。
暂无评论,来抢沙发~