STM32定时器输入捕获测量PWM占空比:DMA与中断模式下的抖动差异及消除方法

1. 引言

在电机控制、电源管理、传感器信号解析等嵌入式应用中,测量外部PWM信号的占空比是核心任务。STM32的定时器输入捕获功能能够精确记录边沿事件的时间戳,但实际测量值常伴有抖动(jitter),影响控制精度。本文将聚焦于使用输入捕获+中断输入捕获+DMA两种模式,分析抖动产生的机理、差异,并给出消除或抑制抖动的实用方案。

2. 输入捕获测量PWM的基本原理

STM32定时器(如TIM2、TIM3等)可配置为输入捕获模式,通过检测通道上的上升沿或下降沿,将当前计数器值锁存到捕获寄存器(CCRx)。测量PWM占空比通常采用双通道捕获单通道交替捕获

  • 方法A:使用两个通道,一个捕获上升沿(周期),一个捕获下降沿(高电平时间)。
  • 方法B:单通道配置为上升沿和下降沿都捕获(需使用PWM输入模式),通过捕获/比较寄存器记录两次边沿。

占空比 = 高电平时间 / 周期。

3. 中断模式下的抖动来源

在中断模式下,每次捕获事件触发CPU中断,软件读取CCRx值并计算。抖动主要来自:

  • 中断响应延迟:从捕获事件到进入中断服务函数(ISR)存在延迟,包括硬件中断仲裁、压栈、以及可能被其他高优先级中断抢占。延迟时间通常为几十到几百个CPU周期,且不固定,导致读取CCRx时计数器可能已更新(若溢出),或计算时引入时间偏移。
  • 软件处理时间:ISR中执行多条指令(读取、计算、存储)耗时,若在捕获发生后、读取前发生定时器溢出,则读数错误。
  • 优先级冲突:若系统中有多个中断源,捕获中断可能被延迟,加剧抖动。

示例代码(中断模式):

// 定时器初始化(略)
void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
        uint32_t capture = TIM_GetCapture1(TIM2); // 读取捕获值
        // 计算占空比(需处理溢出)
        // ...
    }
}

4. DMA模式的优势与抖动分析

DMA模式中,捕获事件触发DMA传输,将CCRx值自动搬运到内存,无需CPU干预。抖动主要来自:

  • DMA传输延迟:DMA请求到实际传输有固定延迟(通常几个时钟周期),但该延迟是确定性的,不随系统负载变化,因此抖动较小。
  • 内存访问冲突:若DMA与CPU同时访问总线,可能产生等待周期,但STM32的DMA控制器优先级可配置,且传输通常很快(一次32位传输约几个周期)。
  • 缓冲区管理:若使用循环缓冲区,需处理数据同步,但不会引入时间抖动。

DMA模式显著降低了软件延迟,但抖动并未完全消除,主要剩余抖动来自硬件本身的捕获精度(如计数器时钟分辨率)和DMA传输的确定性延迟。

5. 抖动差异对比

| 模式 | 抖动来源 | 典型抖动范围 | 适用场景 | |------|----------|--------------|----------| | 中断 | 中断延迟、软件处理、优先级抢占 | 微秒级甚至更大 | 低速信号、对实时性要求不高的场合 | | DMA | 硬件捕获精度、DMA传输延迟 | 亚微秒级 | 高频PWM、高精度测量、实时控制 |

实验表明,在72MHz主频下,中断模式抖动可达±5μs,而DMA模式通常小于±0.5μs。

6. 消除抖动的方法

6.1 优化中断模式

  • 提高中断优先级:将捕获中断设为最高优先级,减少抢占延迟。
  • 使用中断+定时器溢出中断:在溢出中断中记录溢出次数,并在捕获中断中结合溢出次数计算完整时间戳,避免计数器回绕错误。
  • 减少ISR工作量:在ISR中仅读取捕获值并存入全局变量,计算放到主循环或低优先级任务。
volatile uint32_t capture_val;
volatile uint8_t capture_flag;

void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1)) {
        capture_val = TIM_GetCapture1(TIM2);
        capture_flag = 1;
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    }
}

6.2 采用DMA模式

  • 配置DMA循环模式:将捕获值连续传输到数组,避免CPU干预。
  • 使用双缓冲:DMA传输到两个缓冲区,一个用于采集,一个用于处理,防止数据覆盖。
  • 结合定时器溢出中断:DMA传输捕获值,溢出中断记录溢出次数,软件综合计算。
// DMA配置示例
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CCR1;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)capture_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
// 使能DMA
DMA_Cmd(DMA1_Channel2, ENABLE);
// 使能捕获DMA请求
TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);

6.3 硬件滤波与时钟同步

  • 输入滤波:在捕获引脚上配置数字滤波器(如TIM_ICFilter),滤除毛刺,减少误触发。
  • 使用更高分辨率时钟:若定时器时钟为72MHz,则计数周期约13.9ns,提高时钟频率可降低量化误差。

6.4 软件后处理

  • 多次测量取平均:对连续多次占空比测量值进行滤波(如移动平均),消除随机抖动。
  • 中值滤波:去除异常值,适用于噪声较大的环境。

7. 注意事项

  • 定时器溢出处理:无论哪种模式,都必须处理计数器溢出,否则长时间测量会出错。建议使用溢出中断并记录溢出次数。
  • DMA缓冲区大小:需根据PWM频率和测量周期合理设置,避免缓冲区溢出或数据未及时处理。
  • 中断与DMA优先级:若同时使用,需合理配置优先级,避免死锁或数据丢失。
  • 代码可移植性:不同STM32系列(F1、F4、H7)的DMA和定时器寄存器略有差异,需参考对应参考手册。

8. 总结

在STM32定时器输入捕获测量PWM占空比时,DMA模式相比中断模式具有更低的抖动,因为其消除了软件延迟的不确定性。但DMA并非万能,仍需结合硬件滤波、溢出处理和软件滤波来达到最佳精度。开发者应根据实际应用需求(如信号频率、精度要求、CPU负载)选择合适模式,并采取相应优化措施。

通过本文的对比和消除方法,相信你能在嵌入式项目中有效提升PWM测量的稳定性。