## 一、为什么需要互补输出与死区? 在 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()` 分别启动主输出和互补输出。 ```c // 关键代码:主定时器和互补输出同时使能 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。 ```c /* 定时器初始化(由 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 决定),且可配置是否自动恢复。 ```c sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; // 假设故障低电平有效 // 使能刹车后需显式使能主输出 __HAL_TIM_MOE_ENABLE(&htim1); ``` 此时一旦 BKIN 变为有效电平,输出立即关断,无需 CPU 干预,可靠性远高于中断软件响应。 ## 总结 互补输出与死区控制是电机驱动类项目的核心保障,借助 STM32 高级定时器,仅需少量配置即可实现稳定可靠的波形。掌握死区计算、刹车机制和常见调试技巧,能显著提升专业能力。建议在逻辑分析仪上观察 CH1 与 CH1N 波形,验证死区是否在预期范围。