一、为什么需要互补输出与死区?

在 H 桥或三相逆变电路中,同一桥臂的上下两个功率管(如 MOSFET 或 IGBT)需要交替导通。若同时导通,将直接导致电源短路,烧毁器件。

互补输出(Complementary Output) 让定时器自动生成一对极性相反(带可编程延时)的 PWM 信号,分别驱动上下管。而 死区(Dead Time) 就是插入在上下管切换之间的短暂延时,确保一个管子完全关断后,另一个才开启。

经典案例:STM32 TIM1_CH1 与 TIM1_CH1N 即为互补输出对,常用于驱动 IR2104 等栅极驱动芯片。

二、死区时间如何计算?

STM32 高级定时器的死区由寄存器 TIMx_BDTR 的 DTG[7:0] 位控制,其标称时间与定时器时钟 tCK_INT 相关,且存在多档位非线性映射。

主频 64MHz(tCK_INT = 15.625ns)为例,若需 1μs 死区:

  • DTG[7:5] = 100 时,死区 = (64 + DTG[4:0]) × 2 × tCK_INT
  • 代入计算:(64 + DTG[4:0]) × 31.25ns = 1000ns → DTG[4:0] ≈ 32 但超范围(最大31)

此时应选下一档:DTG[7:5] = 101,死区 = (32 + DTG[4:0]) × 4 × tCK_INT = (32+DTG)×62.5ns,取 (32+DTG) = 16 超出。

更推荐做法:在 CubeMX 中直接填入所需时间(如 1μs),工具会自动计算 DTG 值,无需手工换算。

三、HAL 库配置步骤(基于 CubeMX)

  1. 时钟配置:启用定时器时钟(如 APB2 定时器时钟为 64MHz),并确认内部时钟源已勾选。
  2. 参数设置
    • Preemption Priority / Sub Priority 按需配置
    • Mode = PWM Generation CH1 CH1N(或 CH2/CH3)
    • Pulse 设置初始占空比(16位)
    • Output idle state 建议设为 Low(防止意外导通)
  3. 死区设置:在 Break and Dead Time management 中,勾选 DeadTime,填入实际时间(单位 ns)。注意:死区不仅作用于互补对,也会影响刹车后的恢复。
  4. 生成代码后,别忘了在 main() 中调用 HAL_TIM_PWM_Start()HAL_TIMEx_PWMN_Start() 分别启动主输出和互补输出。
// 关键代码:主定时器和互补输出同时使能
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);

四、完整代码示例(调节占空比与死区)

下面代码演示初始化 TIM1 通道1产生 20kHz PWM(占空比 50%),并带 1μs 死区。开发环境:STM32F407 + CubeMX + HAL。

/* 定时器初始化(由 CubeMX 生成,关键参数已标注) */
void MX_TIM1_Init(void) {
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 64 - 1;       // 64MHz/64 = 1MHz
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = 50 - 1;          // 1MHz/50 = 20kHz
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 25;                // 占空比 50%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 64;  // 64 × tCK_INT = 1μs(tCK=15.625ns时)
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; // 先用软件使能,刹车功能见下文
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

    HAL_TIM_PWM_Init(&htim1);
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
    HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
}

/* 占空比动态更新示例:设置为 30% */
void set_duty(uint16_t percent) {
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint16_t)(percent * htim1.Init.Period / 100));
}

/* 启用输出(含死区) */
void pwm_start(void) {
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    // 注意:若设置了 BreakState=ENABLE,还需调用 __HAL_TIM_MOE_ENABLE(&htim1) 使能主输出
}

五、注意事项与常见坑

  • 主输出使能:若启用了刹车功能(BreakState = ENABLE),必须调用 __HAL_TIM_MOE_ENABLE(&htim1) 才能输出波形,否则 PWM 不工作。这在调试时极易被忽略。
  • 死区过小/过大:死区过小会导致上下管共通,死区过大会增加波形失真和发热。通常建议 0.5~2μs,具体看功率管栅极电荷和驱动能力。
  • 刹车引脚极性BreakPolarity 默认高电平有效,若外部刹车信号是低电平触发,务必在 CubeMX 中修改极性,否则反。
  • 互补通道复用:TIM1_CH1N 默认映射在 PB13 等引脚,需确认原理图,防止复用冲突。
  • 空闲状态设置:在电机停转或故障时,输出建议落入已知状态(如低电平),避免悬空导致门极误触发。

六、进阶:利用刹车功能实现硬件急停

电机驱动中,过流或过压信号应快速封锁 PWM。将故障信号接至 TIM1 的 BKIN 引脚,配置 BreakState = ENABLE 后,硬件自动强制输出为安全电平(由 IdleState 决定),且可配置是否自动恢复。

sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; // 假设故障低电平有效
// 使能刹车后需显式使能主输出
__HAL_TIM_MOE_ENABLE(&htim1);

此时一旦 BKIN 变为有效电平,输出立即关断,无需 CPU 干预,可靠性远高于中断软件响应。

总结

互补输出与死区控制是电机驱动类项目的核心保障,借助 STM32 高级定时器,仅需少量配置即可实现稳定可靠的波形。掌握死区计算、刹车机制和常见调试技巧,能显著提升专业能力。建议在逻辑分析仪上观察 CH1 与 CH1N 波形,验证死区是否在预期范围。