一、为什么需要互补输出与死区?
在 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)
- 时钟配置:启用定时器时钟(如 APB2 定时器时钟为 64MHz),并确认内部时钟源已勾选。
-
参数设置:
- Preemption Priority / Sub Priority 按需配置
- Mode = PWM Generation CH1 CH1N(或 CH2/CH3)
- Pulse 设置初始占空比(16位)
- Output idle state 建议设为 Low(防止意外导通)
- 死区设置:在 Break and Dead Time management 中,勾选 DeadTime,填入实际时间(单位 ns)。注意:死区不仅作用于互补对,也会影响刹车后的恢复。
-
生成代码后,别忘了在
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 波形,验证死区是否在预期范围。