3、防短路核心逻辑:直通现象、死区时间与PWM控制

各位工程师朋友,今天我们来聊聊直流电机H桥驱动中最要命的问题——短路

我刚开始做电机驱动那会儿,就吃过这个亏。板子一上电,MOS管直接冒烟,吓得我赶紧拔电源。后来一查,就是典型的“直通”问题。说白了,就是上下两个管子同时导通了。

3.1 直通(Shoot-through)现象分析

什么叫直通?我画个简图你就明白了。

H桥直通现象示意图 VCC (12V) Q1 (导通) Q2 (关断) Q3 (关断) Q4 (导通) M 电机 GND GND 直通电流! 💥

你看这个H桥,正常工作时,Q1和Q4导通,电流从VCC→Q1→电机→Q4→GND,电机正转。反过来Q2和Q3导通,电机反转。

但问题来了——如果Q1还没完全关断,Q2就已经导通了,会发生什么?

⚠️ 直通后果:
  • VCC直接对GND短路,电流瞬间飙升
  • MOS管在几微秒内过热烧毁
  • 严重时可能炸管、烧PCB铜箔
  • 电源电压会被瞬间拉低,影响其他电路

我在一个项目中就遇到过这种情况。当时用的是IR2104驱动芯片,死区时间设得太短,结果上电测试时,MOS管直接炸了,碎片崩到脸上,还好戴了护目镜。从那以后,我对死区时间就特别敏感。

3.2 死区时间(Dead Time)概念

死区时间,说白了就是故意插入的一段“空白期”

在这段时间里,上下两个管子都关断。谁都不导通,自然就不会直通了。

参数 说明 典型值
死区时间 上下管都关断的时间间隔 100ns ~ 2μs
MOS管关断延迟 从栅极信号到完全关断的时间 20ns ~ 100ns
MOS管导通延迟 从栅极信号到完全导通的时间 15ns ~ 80ns
安全裕量 死区时间减去开关延迟 建议 ≥ 50ns

嗯,这里要注意:死区时间不是越长越好。太长了,电机电流会断续,产生噪音和振动。太短了,又可能直通。我一般取开关延迟的2~3倍作为起步值。

💡 我的经验: 对于常用的IRF540这类MOS管,死区时间设在500ns左右比较稳妥。如果用的是SiC或GaN器件,开关速度更快,死区可以缩到100ns以内。

3.3 互补PWM与独立PWM控制

讲完死区,我们来看看两种常见的PWM控制方式。

3.4.1 互补PWM(Complementary PWM)

互补PWM,就是上下两个管的控制信号正好相反。上管高电平时,下管低电平;上管低电平时,下管高电平。

但直接这样用肯定不行——你想想看,信号翻转需要时间,翻转过程中就可能直通。所以要在翻转之间插入死区。

// 互补PWM + 死区插入(伪代码)
// 假设PWM频率20kHz,周期50μs
// 死区时间500ns

void generateComplementaryPWM(uint16_t dutyCycle) {
    // 上管导通时间
    uint16_t onTime = dutyCycle;
    // 下管导通时间
    uint16_t offTime = PWM_PERIOD - dutyCycle;
    
    // 插入死区:上管关断后等500ns,下管才导通
    // 下管关断后等500ns,上管才导通
    
    // 实际波形:
    // 上管: ████████______████████______
    // 下管: ________████████______██████
    // 死区:       ↑←500ns→↑     ↑←500ns→↑
}

我习惯用STM32的定时器来做互补PWM。它的高级定时器自带死区插入功能,配置一下就行。

// STM32 互补PWM配置示例
void setupComplementaryPWM(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
    
    // 定时器配置
    TIM_TimeBaseStructure.TIM_Period = 999;  // 20kHz @ 20MHz
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    
    // PWM1模式配置
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;  // 互补输出
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    
    // 死区时间配置:500ns
    TIM_BDTRInitStructure.TIM_DeadTime = 10;  // 500ns @ 20MHz
    TIM_BDTRInit(TIM1, &TIM_BDTRInitStructure);
    
    TIM_Cmd(TIM1, ENABLE);
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

3.4.2 独立PWM(Independent PWM)

独立PWM就灵活多了。上下两个管子的PWM信号完全独立,你可以分别控制它们的占空比和相位。

这样做的好处是:

  • 可以精细控制死区时间
  • 支持更多控制模式(比如同步整流)
  • 调试方便,可以单独测试每个管子

但缺点也很明显——软件复杂度高。你得自己保证上下管不会同时导通。

🔑 核心对比:
特性 互补PWM 独立PWM
硬件复杂度 低(硬件自动插入死区) 高(软件控制)
灵活性 低(固定互补关系) 高(任意波形)
死区控制 硬件自动 软件手动
适用场景 普通电机驱动 高性能/特殊控制
风险 配置错误仍可能直通 软件bug导致直通

我个人习惯是:能用互补PWM就用互补PWM。硬件自动插入死区,省心又可靠。只有在需要特殊控制波形时,才用独立PWM。

3.4 避坑指南

最后,分享几个我踩过的坑:

⚠️ 我曾经犯过的错误:
  1. 死区时间设得太极限——以为100ns就够了,结果温度一高,MOS管开关速度变慢,直接直通。后来我留了3倍裕量。
  2. 忘记考虑MOS管寄生参数——栅极电阻、米勒电容都会影响开关速度。实际死区时间要比计算值大一些。
  3. 软件死区实现有bug——用定时器中断做独立PWM时,中断优先级没处理好,导致死区偶尔丢失。后来改用硬件定时器才解决。
💡 我的建议:
  • 新板子第一次上电,先把死区设大一点(比如2μs),确认没问题再慢慢缩小
  • 用示波器同时看上下管的栅极波形,确认死区存在
  • 温度测试时,在高温和低温下都验证死区是否足够
  • 量产前做短路测试:故意让电机堵转,看驱动电路能否扛住

好了,关于防短路的核心逻辑就讲到这里。死区时间这个东西,说难不难,说简单也不简单。关键是要理解它的本质——用一点点时间损失,换取系统的安全可靠。这个取舍,值得。


公众号:蓝海资料掘金营,微信deep3321