为什么移相全桥需要 HRTIM
移相全桥(Phase-Shifted Full-Bridge, PSFB)通过调节两个桥臂之间的相位差来控制输出功率,相比硬开关拓扑能实现零电压开通(ZVS),降低开关损耗。它的核心时序要求是:
- 每个桥臂的上下管互补导通,且必须插入死区防止直通;
- 两个桥臂之间保持可调的相位差(0~180°);
- 开关频率通常在 100kHz~500kHz,占空比分辨率要求高;
- ADC 采样必须与 PWM 同步,避开开关噪声,保证电流环稳定。
STM32 的通用定时器 TIM1 在 200kHz 以上时占空比调节精度不足,而 HRTIM(High-Resolution Timer)提供 184ps 的分辨率,且自带多定时器同步、死区、ADC 触发等特性,非常适合 PSFB。
HRTIM 关键机制解析
计数与比较单元
HRTIM 包含 Master 定时器和多个 Timer(A~F)。每个 Timer 有独立的计数器和 4 个比较寄存器(CMP1~CMP4),可产生 SET/RESET 事件驱动输出。PSFB 中常用 Timer A 控制超前桥臂,Timer B 控制滞后桥臂。
死区插入
HRTIM 每个输出对(如 TA1/TA2)可配置死区。死区时间由 DTR 寄存器设置,支持上升沿和下降沿独立死区。对 PSFB,死区通常设为 100~300ns,需根据 MOS 管和驱动电路调整。
主从同步
Master 定时器作为全局时基,通过 HRTIM_MCR 的 SYNC 位产生同步事件,触发 Timer A/B 同时复位或启动。这样两个桥臂的相位关系由各自 CMP 值决定,相位差 = (CMP_B - CMP_A) / Period × 360°。
ADC 触发联动
HRTIM 的 ADC 触发事件(ADC1TRG/ADC2TRG)可配置在计数器特定值或比较事件时产生。PSFB 中通常在原边电流峰值附近触发 ADC 采样,避开开关瞬间。
配置步骤(以 STM32G474 为例)
- 使能 HRTIM 时钟,配置 Master 周期为开关周期;
- 配置 Timer A/B 为连续计数模式,由 Master 同步复位;
- 设置各 Timer 的 CMP 值决定占空比和相位;
- 配置输出交叉、死区时间;
- 配置 ADC 触发源为 HRTIM 事件;
- 启动 HRTIM,使能输出。
完整代码示例
以下代码基于 STM32G474,使用 HAL 库初始化 HRTIM 并配置 PSFB 时序。假设开关频率 200kHz,死区 200ns,相位差 90°。
#include "stm32g4xx_hal.h"
HRTIM_HandleTypeDef hhrtim;
/* 开关频率 200kHz,HRTIM 时钟 4.608GHz(等效),Period = 23040 */
#define HRTIM_PERIOD 23040
#define DEADTIME_NS 200
#define PHASE_SHIFT_DEG 90
void HRTIM_PSFB_Init(void)
{
HRTIM_TimeBaseCfgTypeDef tb_cfg = {0};
HRTIM_TimerCfgTypeDef timer_cfg = {0};
HRTIM_OutputCfgTypeDef out_cfg = {0};
HRTIM_ADCTriggerCfgTypeDef adc_trg = {0};
__HAL_RCC_HRTIM1_CLK_ENABLE();
hhrtim.Instance = HRTIM1;
hhrtim.Init.HRTIMInterruptResquests = HRTIM_IT_NONE;
hhrtim.Init.SyncOptions = HRTIM_SYNCOPTION_NONE;
hhrtim.Init.SyncInput = HRTIM_SYNCINPUT_0;
hhrtim.Init.SyncOutput = HRTIM_SYNCOUTPUT_0;
HAL_HRTIM_Init(&hhrtim);
/* Master 定时器:周期 = 开关周期 */
tb_cfg.Period = HRTIM_PERIOD;
tb_cfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
tb_cfg.Mode = HRTIM_MODE_CONTINUOUS;
HAL_HRTIM_TimeBaseConfig(&hhrtim, HRTIM_TIMERINDEX_MASTER, &tb_cfg);
/* Timer A:超前桥臂,占空比 45% */
tb_cfg.Period = HRTIM_PERIOD;
tb_cfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
tb_cfg.Mode = HRTIM_MODE_CONTINUOUS;
HAL_HRTIM_TimeBaseConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A, &tb_cfg);
timer_cfg.InterruptRequests = HRTIM_TIM_IT_NONE;
timer_cfg.DMARequests = HRTIM_TIM_DMA_NONE;
timer_cfg.PreloadEnable = HRTIM_PRELOAD_ENABLE;
timer_cfg.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;
timer_cfg.BurstMode = HRTIM_BURSTMODE_DISABLE;
timer_cfg.PushPull = HRTIM_TIMPUSHPULLMODE_DISABLE;
timer_cfg.FaultEnable = HRTIM_TIMFAULTENABLE_NONE;
timer_cfg.FaultLock = HRTIM_TIMFAULTLOCK_READWRITE;
timer_cfg.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_ENABLE;
timer_cfg.DelayedProtectionMode = HRTIM_TIMER_DELAYEDPROTECTION_DISABLED;
timer_cfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_MASTER_PER;
timer_cfg.UpdateTrigger = HRTIM_TIMUPDATETRIGGER_MASTER_PER;
timer_cfg.ResetUpdate = HRTIM_TIMUPDATEONRESET_ENABLE;
HAL_HRTIM_TimerConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A, &timer_cfg);
/* 设置比较值:CMP1 = 45% 占空比 */
HAL_HRTIM_WaveformSetCompare(&hhrtim, HRTIM_TIMERINDEX_TIMER_A,
HRTIM_COMPAREUNIT_1, HRTIM_PERIOD * 45 / 100);
/* 死区配置:上升沿和下降沿均为 200ns */
HAL_HRTIM_DeadTimeConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A,
HRTIM_TIMDEADTIME_RISING_200NS,
HRTIM_TIMDEADTIME_FALLING_200NS);
/* 输出配置:TA1/TA2 互补 */
out_cfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
out_cfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
out_cfg.ResetSource = HRTIM_OUTPUTRESET_TIMPER;
out_cfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
out_cfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
out_cfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_INACTIVE;
out_cfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLE;
out_cfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
HAL_HRTIM_WaveformOutputConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A,
HRTIM_OUTPUT_TA1, &out_cfg);
out_cfg.SetSource = HRTIM_OUTPUTSET_TIMPER;
out_cfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP1;
HAL_HRTIM_WaveformOutputConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A,
HRTIM_OUTPUT_TA2, &out_cfg);
/* Timer B:滞后桥臂,相位差 90° */
tb_cfg.Period = HRTIM_PERIOD;
tb_cfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
tb_cfg.Mode = HRTIM_MODE_CONTINUOUS;
HAL_HRTIM_TimeBaseConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_B, &tb_cfg);
timer_cfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_MASTER_PER;
timer_cfg.UpdateTrigger = HRTIM_TIMUPDATETRIGGER_MASTER_PER;
timer_cfg.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_ENABLE;
HAL_HRTIM_TimerConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_B, &timer_cfg);
/* 相位差 90°:CMP1 = Period * (90/360) = 25% */
HAL_HRTIM_WaveformSetCompare(&hhrtim, HRTIM_TIMERINDEX_TIMER_B,
HRTIM_COMPAREUNIT_1, HRTIM_PERIOD * 25 / 100);
HAL_HRTIM_DeadTimeConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_B,
HRTIM_TIMDEADTIME_RISING_200NS,
HRTIM_TIMDEADTIME_FALLING_200NS);
out_cfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
out_cfg.ResetSource = HRTIM_OUTPUTRESET_TIMPER;
HAL_HRTIM_WaveformOutputConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_B,
HRTIM_OUTPUT_TB1, &out_cfg);
out_cfg.SetSource = HRTIM_OUTPUTSET_TIMPER;
out_cfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP1;
HAL_HRTIM_WaveformOutputConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_B,
HRTIM_OUTPUT_TB2, &out_cfg);
/* ADC 触发:在 Timer A 的 CMP2 事件触发 ADC1 */
adc_trg.Trigger = HRTIM_ADCTRIGGEREVENT13_TIMERA_CMP2;
adc_trg.UpdateSource = HRTIM_ADCTRIGGERUPDATE_TIMER_A;
HAL_HRTIM_ADCTriggerConfig(&hhrtim, HRTIM_ADCTRIGGER_1, &adc_trg);
/* 启动 HRTIM */
HAL_HRTIM_WaveformCounterStart(&hhrtim, HRTIM_TIMERID_MASTER |
HRTIM_TIMERID_TIMER_A |
HRTIM_TIMERID_TIMER_B);
HAL_HRTIM_WaveformOutputStart(&hhrtim, HRTIM_OUTPUT_TA1 | HRTIM_OUTPUT_TA2 |
HRTIM_OUTPUT_TB1 | HRTIM_OUTPUT_TB2);
}
注意事项与调试建议
- 死区时间:必须根据驱动芯片和 MOS 管参数实测调整,过小会直通炸管,过大会降低效率。建议用示波器观察桥臂中点波形确认。
- 相位差更新:在运行中改变相位差时,应使用预装载(Preload)功能,在更新事件时生效,避免毛刺。
- ADC 触发点:采样点应避开开关瞬间和死区,通常选择在原边电流平稳段。可通过调整 CMP2 值微调。
- 同步信号:多相交错时,可用 Master 的 SYNC 输出同步其他 HRTIM 或外部芯片。
- 故障保护:务必配置 Fault 输入,过流时快速封锁输出,HRTIM 支持逐周期限流。
-
时钟精度:HRTIM 高分辨率依赖校准,建议在初始化时调用
HAL_HRTIM_Init后执行校准流程。
通过以上配置,STM32 HRTIM 可以稳定驱动移相全桥,实现高精度相位控制和可靠的 ADC 同步采样,为数字电源的闭环控制打下基础。