4、死区时间插入与配置:避免上下桥臂直通的关键
死区时间,说白了就是给上下桥臂切换时留出的「安全缓冲期」。
我刚开始做电机驱动那会儿,觉得死区就是个麻烦事——它会让波形失真,还会限制最高频率。直到有一次,我在调试一个 24V 的直流无刷电机驱动板,手一抖把死区设成了 0……结果你猜怎么着?MOSFET 直接冒烟了。嗯,从那以后,我再也不敢小看死区了。
为什么需要死区时间?
H 桥驱动电路里,上下两个开关管是交替导通的。但问题是,任何开关器件都有关断延迟。上管还没完全关断,下管就开始导通了——这就叫「直通」,也叫「穿通」。直通瞬间,电源直接短路,电流飙升,管子秒烧。
核心结论:死区时间 = 上下桥臂切换时,两者都关断的「安全间隔」。没有死区,就没有可靠的 H 桥驱动。
我见过不少新手,在仿真里跑得好好的,一上硬件就炸管。为什么?因为仿真模型里的开关是理想的,而现实中的 MOSFET 或 IGBT 有结电容、有米勒效应、有存储时间。你想想看,这些非理想特性叠加起来,关断延迟少说也有几十纳秒到几百纳秒。
死区时间怎么算?
死区时间不是拍脑袋定的。它取决于三个因素:
| 因素 | 说明 | 典型值 |
|---|---|---|
| 开关管关断延迟 | 从驱动信号撤去到管子完全关断的时间 | 50~200 ns |
| 驱动芯片传播延迟 | 驱动芯片内部信号传输的延迟差异 | 20~100 ns |
| 系统安全裕量 | 考虑温度、批次差异的余量 | 100~500 ns |
我个人习惯这样估算:
死区时间 = (关断延迟最大值 + 驱动延迟最大值) × 1.5 ~ 2
举个例子,如果你用的 MOSFET 关断延迟最大 150 ns,驱动芯片延迟最大 50 ns,那死区时间至少设到 (150+50)×1.5 = 300 ns。保守一点我会设到 500 ns。
注意:死区时间不是越大越好。死区太大,波形畸变严重,电机电流谐波增加,效率下降,甚至会引起转矩脉动。我见过有人为了保险,死区设到 3 μs,结果电机低速运行时抖得像筛子。
STM32 高级定时器的死区配置
STM32 的高级定时器(TIM1、TIM8 等)内置了死区插入硬件。你只需要配置几个寄存器,硬件会自动在互补 PWM 信号中插入死区,不需要软件干预。这一点非常方便。
核心寄存器是 TIMx_BDTR(刹车和死区寄存器)。它的 DTG[7:0] 位域用来设置死区时长。
死区时间的计算公式分两种情况:
| DTG[7:0] 范围 | 死区时间计算公式 | 步长 |
|---|---|---|
| 0x00 ~ 0x7F | DT × Tck | 1 × Tck |
| 0x80 ~ 0xFF | (64 + DTG[5:0]) × Tck × 2 | 2 × Tck |
其中 Tck 是定时器的时钟周期。如果定时器时钟是 72 MHz,Tck ≈ 13.89 ns。
假设我想要 500 ns 的死区:
500 / 13.89 ≈ 36
所以 DTG = 36 = 0x24,属于 0x00~0x7F 范围,死区 = 36 × 13.89 ≈ 500 ns。
代码实战:HAL 库配置死区
用 STM32CubeMX 配置时,在 TIM1 的「Break and Dead-Time」选项卡里直接填死区时间(单位 ns),工具会自动算好 DTG 值。但如果你像我一样喜欢手写代码,可以这样配:
// 假设定时器时钟 72 MHz,目标死区 500 ns
// Tck = 1/72MHz ≈ 13.89 ns
// DTG = 500 / 13.89 ≈ 36 = 0x24
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 36; // DTG 值
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
// 别忘了使能主输出
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // 启动互补通道
小技巧:调试时可以用示波器同时看 CH1 和 CH1N 的波形,测量死区时间是否准确。我曾经遇到过一个问题:代码里配了死区,但示波器上看不到。后来发现是忘了调用 HAL_TIMEx_PWMN_Start()——互补通道没使能,自然没有输出。
死区插入的波形与知识结构
下面这张图帮你理清死区配置的完整逻辑:
调试中的常见坑
我总结几个实际项目中踩过的坑,你遇到了可以少走弯路:
- 死区配了但没效果——检查是否调用了
HAL_TIMEx_PWMN_Start(),互补通道必须单独启动。 - 死区时间比配置值大很多——看看定时器时钟分频是不是设错了。我遇到过有人把 TIM 时钟设成了 36 MHz 却按 72 MHz 算 DTG,结果死区翻倍。
- 电机低速抖动——死区可能太大了。试着用示波器量一下实际死区,然后逐步减小,直到波形刚好不出现直通。
- 上电瞬间炸管——检查刹车(Break)引脚的电平状态。STM32 的刹车功能默认是低电平有效,如果刹车引脚悬空,可能会误触发或导致输出异常。
重要提醒:调试 H 桥驱动时,建议先在电源回路里串一个限流电阻(比如 10 Ω/5W),或者用可调电源限流到 0.5A。这样就算死区没配好,也不会立刻炸管。我吃过这个亏,现在每次上电前都会做这个「保命操作」。
死区对 PWM 波形的影响
死区插入后,PWM 波形会有一个「缺口」。这个缺口会导致输出电压的平均值略微下降,在低速或轻载时尤其明显。这就是所谓的「死区效应」。
解决死区效应的方法有两种:
- 硬件补偿——在驱动芯片里做死区补偿,比如 IR2104 这类芯片自带死区,但补偿精度有限。
- 软件补偿——在算法里根据死区时间和电流方向,对占空比做修正。FOC 算法里通常会做这个补偿,后面章节会详细讲。
嗯,死区时间这部分内容就到这里。记住一句话:死区是 H 桥驱动的「安全带」,系好了才能安全上路。