基于STM32G4的HRTIM高分辨率定时器实现多路交错PWM的相位抖动抑制
👁 2 阅读 · 2026-08-27 · 嵌入式
STM32G4系列内置的高分辨率定时器(HRTIM)以184皮秒的时间分辨率著称,特别适合数字电源、电机控制等对PWM精度要求极高的场景。然而,在多路交错PWM输出时,由于定时器同步误差、中断延迟和死区插入等因素,容易产生相位抖动,影响系统性能。本文深入剖析HRTIM的架构与相位抖动根源,并给出一种基于硬件同步和DMA预装载的抖动抑制方案,附带完整代码示例,帮助开发者充分发挥HRTIM的潜力。
# 基于STM32G4的HRTIM高分辨率定时器实现多路交错PWM的相位抖动抑制
## 一、HRTIM与相位抖动问题概述
STM32G4的HRTIM(High-Resolution Timer)由多个子定时器(Timer A~F)组成,每个子定时器可独立生成PWM,且支持主从同步和外部事件触发。其核心优势在于采用延迟锁定环(DLL)技术,将时钟周期细分为多个相位,实现皮秒级分辨率。
在多路交错PWM应用中(如三相逆变器、多相Buck变换器),各通道需按固定相位差(如120°或360°/N)输出。理想情况下,相位差应恒定不变,但实际中常出现抖动(jitter),表现为脉冲边沿位置随机偏移,导致电流纹波增大、电磁干扰恶化。
**相位抖动的主要来源:**
- 软件中断响应延迟:更新占空比时,若在中断中修改寄存器,调度延迟会直接反映为相位偏移。
- 定时器同步误差:多个子定时器虽可硬件同步,但若配置不当,启动时刻不一致。
- 死区插入不对称:死区生成逻辑在上升沿和下降沿的延迟可能不同。
- 电源噪声和温度漂移:影响DLL校准精度。
## 二、硬件架构与同步机制
HRTIM的每个子定时器拥有独立的比较寄存器(CMPx)和周期寄存器(PERx),并支持以下同步方式:
- **主从级联**:通过SYNC_OUT和SYNC_IN信号,一个定时器可作为主设备,触发其他从设备复位或启动。
- **外部事件同步**:支持外部信号(如GPIO)触发所有定时器同时复位。
- **DMA请求**:比较事件或更新事件可触发DMA传输,实现寄存器预装载。
对于多路交错PWM,推荐使用**主定时器(如Timer A)产生基准周期,其他定时器(Timer B~F)配置为从模式,通过SYNC信号复位**,从而保证所有通道的周期起点一致。
## 三、相位抖动抑制策略
### 1. 硬件同步启动,避免软件干预
所有子定时器在初始化时,通过设置`HRTIM_MCR_SYNC_IN`位,使能同步输入。然后在主定时器启动时,自动触发从定时器复位。这样,各通道的起始相位完全由硬件决定,消除软件启动延迟。
### 2. 使用DMA预装载比较值
传统做法是在中断中更新CMPx寄存器,但中断延迟不可控。改为使用DMA:当更新事件发生时,DMA自动从内存搬运新的比较值到CMPx寄存器,整个过程无需CPU介入,且DMA传输由硬件时钟驱动,延迟固定。
### 3. 优化死区配置
HRTIM支持可编程死区,且上升沿和下降沿可独立设置。为减小不对称,应确保上升沿延迟和下降沿延迟相等,并采用硬件死区而非软件插入。
### 4. 校准DLL
HRTIM内置DLL,需在初始化时调用`HAL_HRTIM_DLLCalibrationStart()`进行校准,并在运行中定期检查校准状态,防止温度漂移导致分辨率下降。
## 四、代码实现:三相交错PWM(相位差120°)
以下示例使用Timer A、B、C生成三路PWM,频率100kHz,占空比50%,相位差120°。
### 1. 初始化时钟和GPIO
```c
// 使能HRTIM时钟和GPIO时钟
__HAL_RCC_HRTIM1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置PA8、PA9、PA10为HRTIM输出(需查手册复用功能)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF13_HRTIM1; // 根据具体型号调整
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
```
### 2. HRTIM配置
```c
HRTIM_HandleTypeDef hrtim1;
HRTIM_TimeBaseCfgTypeDef sTimeBaseCfg;
HRTIM_TimerCfgTypeDef sTimerCfg;
HRTIM_CompareCfgTypeDef sCompareCfg;
// 使能HRTIM
hrtim1.Instance = HRTIM1;
HAL_HRTIM_Init(&hrtim1);
// 配置主定时器A:周期100kHz(假设时钟170MHz,周期值=1700-1)
sTimeBaseCfg.Period = 1700 - 1;
sTimeBaseCfg.RepetitionCounter = 0;
sTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_DIV1;
sTimeBaseCfg.Mode = HRTIM_MODE_CONTINUOUS;
HAL_HRTIM_TimeBaseConfig(&hrtim1, HRTIM_TIMERINDEX_MASTER, &sTimeBaseCfg);
// 配置从定时器B和C,使用同步复位
sTimerCfg.InterruptRequests = HRTIM_TIM_INTERRUPT_NONE;
sTimerCfg.DMARequests = HRTIM_TIM_DMA_UPDATE;
sTimerCfg.DMASrc = HRTIM_TIM_DMA_SRC_UPDATE;
sTimerCfg.HalfMode = HRTIM_HALFMODE_DISABLED;
sTimerCfg.StartSync = HRTIM_TIM_SYNC_START; // 由主定时器同步启动
HAL_HRTIM_TimerConfig(&hrtim1, HRTIM_TIMERINDEX_TIMER_B, &sTimerCfg);
HAL_HRTIM_TimerConfig(&hrtim1, HRTIM_TIMERINDEX_TIMER_C, &sTimerCfg);
// 配置比较值:A在50%处翻转,B在50%+120°处,C在50%+240°处
// 周期1700,50%为850,120°对应566.7,取整567
sCompareCfg.CompareValue = 850;
HAL_HRTIM_CompareConfig(&hrtim1, HRTIM_TIMERINDEX_MASTER, HRTIM_COMPAREUNIT_1, &sCompareCfg);
sCompareCfg.CompareValue = (850 + 567) % 1700; // 1417
HAL_HRTIM_CompareConfig(&hrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_COMPAREUNIT_1, &sCompareCfg);
sCompareCfg.CompareValue = (850 + 1134) % 1700; // 284
HAL_HRTIM_CompareConfig(&hrtim1, HRTIM_TIMERINDEX_TIMER_C, HRTIM_COMPAREUNIT_1, &sCompareCfg);
// 配置输出:PWM模式1,高电平有效,死区关闭(简化)
HRTIM_OutputCfgTypeDef sOutputCfg = {0};
sOutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
sOutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
sOutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMPER;
HAL_HRTIM_OutputConfig(&hrtim1, HRTIM_TIMERINDEX_MASTER, HRTIM_OUTPUT_1, &sOutputCfg);
// 类似配置B和C的输出,略
```
### 3. 启动HRTIM和DMA
```c
// 启动DMA传输(需预先定义数组存储比较值)
// 假设dmaBuf[3] = {850, 1417, 284},每次更新事件自动加载
HAL_HRTIM_DMAStart(&hrtim1, HRTIM_TIMERINDEX_MASTER, HRTIM_DMA_UPDATE, (uint32_t*)dmaBuf, 3);
// 启动主定时器,从定时器自动同步启动
HAL_HRTIM_WaveformCounterStart(&hrtim1, HRTIM_TIMERINDEX_MASTER);
HAL_HRTIM_WaveformCounterStart(&hrtim1, HRTIM_TIMERINDEX_TIMER_B);
HAL_HRTIM_WaveformCounterStart(&hrtim1, HRTIM_TIMERINDEX_TIMER_C);
```
## 五、注意事项
- **同步启动顺序**:务必先配置从定时器的`StartSync`为`HRTIM_TIM_SYNC_START`,再启动主定时器,否则从定时器不会自动同步。
- **DMA缓冲区**:DMA传输的数据宽度需与寄存器匹配(32位),且缓冲区需在内存中保持有效。
- **死区设置**:若需死区,使用`HAL_HRTIM_DeadTimeConfig`,并确保上升沿和下降沿延迟一致。
- **DLL校准**:在初始化后调用`HAL_HRTIM_DLLCalibrationStart`,并等待校准完成标志,否则分辨率可能不达标。
- **中断优先级**:若仍需中断(如故障保护),应将其优先级设为最高,并避免在中断中执行耗时操作。
## 六、总结
通过硬件同步和DMA预装载,可有效抑制多路交错PWM的相位抖动,充分发挥STM32G4 HRTIM的高分辨率优势。本文提供的代码框架可直接应用于数字电源或电机控制项目,开发者可根据实际需求调整通道数和相位差。