为什么移相全桥需要 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 为例)

  1. 使能 HRTIM 时钟,配置 Master 周期为开关周期;
  2. 配置 Timer A/B 为连续计数模式,由 Master 同步复位;
  3. 设置各 Timer 的 CMP 值决定占空比和相位;
  4. 配置输出交叉、死区时间;
  5. 配置 ADC 触发源为 HRTIM 事件;
  6. 启动 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 同步采样,为数字电源的闭环控制打下基础。