3. 电机控制核心:H桥驱动原理、死区时间设置、互补PWM输出配置

好,咱们进入电机控制最核心的部分。说白了,你要让电机转起来、转得稳、转得准,绕不开H桥、死区和互补PWM这三个东西。我刚开始做电机驱动那会儿,觉得不就是让几个管子导通嘛,结果一上电就炸管——嗯,从那以后我再也不敢小看这几个细节了。

3.1 H桥驱动原理:让电机正反转的核心

H桥的名字很形象,四个开关管搭成一个“H”形状,电机就是中间那根横梁。控制逻辑其实很简单:

  • 正转:Q1和Q4导通,电流从左往右流过电机
  • 反转:Q2和Q3导通,电流从右往左流过电机
  • 刹车:Q1和Q3同时导通(或Q2和Q4),电机两端短路
  • 滑行:所有管子关断,电机自由旋转

我在一个直流有刷电机项目里遇到过一个问题:正反转切换时电机突然卡死。查了半天,发现是切换顺序没处理好——先关了所有管子再重新导通,中间有个“全关”状态,电机反电动势把管子击穿了。后来我改成先导通目标管子再关断当前管子,问题就解决了。

关键点:H桥的四个管子绝对不能同时导通,否则就是电源对地短路——我们叫它“直通”,一秒钟就能把MOS管烧冒烟。

H桥驱动电路结构 VCC Q1 Q2 电机 M Q3 Q4 GND 正转电流 反转电流 Q1/Q4导通 → 正转 | Q2/Q3导通 → 反转 | 严禁Q1/Q2或Q3/Q4同时导通

3.2 死区时间设置:为什么需要“等一等”

你想想看,MOS管不是理想开关。从导通到关断需要时间,从关断到导通也需要时间。如果上管还没完全关断,下管就导通了——直通!

死区时间就是故意插入的一段“等待时间”。在这段时间里,两个管子都关断,等一个管子彻底关断了,再让另一个管子导通。

参数 典型值 说明
MOS管关断延迟 20-50 ns 从栅极信号到完全关断
MOS管导通延迟 10-30 ns 从栅极信号到完全导通
死区时间 100-500 ns 建议留2-3倍余量
死区过长的影响 波形畸变 电机噪音大、效率低
死区过短的影响 直通烧管 MOS管瞬间过热损坏

我曾经在一个项目中把死区时间设成了50ns,觉得够用了。结果上电测试,MOS管温度飙升,不到10秒就冒烟了。后来查手册发现,我用的那款MOS管关断延迟就有80ns。死区时间一定要大于管子最差情况下的关断延迟。

3.3 互补PWM输出配置:CMS32的定时器设置

互补PWM,就是一对PWM信号,一个高的时候另一个低,中间插入死区时间。CMS32的定时器模块专门支持这个功能。

我习惯用高级定时器(比如TIM1或TIM8)来做电机控制,因为它们有硬件死区插入功能。软件模拟死区?嗯,我试过,中断响应不及时就容易出问题。

3.3.1 配置步骤

  1. 选择定时器:使用高级定时器TIM1或TIM8
  2. 设置PWM模式:通道配置为PWM模式1或2
  3. 配置互补输出:使能CHxN互补通道
  4. 设置死区时间:写入TIMx_BDTR寄存器的DTG位
  5. 使能输出:设置TIMx_BDTR的MOE位

3.3.2 代码示例:CMS32互补PWM配置

// CMS32 互补PWM配置示例
void Motor_PWM_Init(void)
{
    // 1. 使能定时器时钟
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
    
    // 2. 配置GPIO为复用功能
    // PA8: TIM1_CH1, PA9: TIM1_CH2, PA10: TIM1_CH3
    // PA11: TIM1_CH1N, PA12: TIM1_CH2N, PA13: TIM1_CH3N
    GPIOA->CRH = 0xBBBBBBBB;  // 复用推挽输出
    
    // 3. 定时器基础配置
    TIM1->PSC = 71;           // 72MHz / (71+1) = 1MHz
    TIM1->ARR = 999;          // 1MHz / (999+1) = 1kHz PWM频率
    
    // 4. 配置PWM模式1 (向上计数时,CNT < CCR时输出有效)
    TIM1->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;  // PWM模式1
    TIM1->CCMR1 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
    TIM1->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
    
    // 5. 使能互补输出
    TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE;  // CH1和CH1N
    TIM1->CCER |= TIM_CCER_CC2E | TIM_CCER_CC2NE;
    TIM1->CCER |= TIM_CCER_CC3E | TIM_CCER_CC3NE;
    
    // 6. 设置死区时间 (BDTR寄存器)
    // DTG[7:0] = 100, 死区时间 = 100 * tDTS = 100 * 1us = 100us
    TIM1->BDTR = (100 << 0) | TIM_BDTR_MOE;  // MOE: 主输出使能
    
    // 7. 设置占空比 (初始50%)
    TIM1->CCR1 = 500;
    TIM1->CCR2 = 500;
    TIM1->CCR3 = 500;
    
    // 8. 使能定时器
    TIM1->CR1 |= TIM_CR1_CEN;
}

个人习惯:我一般把死区时间设成PWM周期的1%-3%。比如1kHz的PWM,周期是1ms,死区时间设10-30us。这样既安全,又不会明显影响波形质量。

3.4 死区时间对波形的影响

死区时间设得太长,波形会“缺一块”。你想想看,本来应该连续输出的电压,中间硬生生断了一截。电机电流会变得不连续,产生噪音和转矩脉动。

设得太短呢?直通风险。我见过一个同行,为了追求波形完美,把死区时间压到极限。结果量产的时候,一批MOS管参数有偏差,直通率直接掉了30%。

所以我的建议是:

  • 开发阶段:死区时间设大一点(比如500ns),先保证不炸管
  • 调试阶段:用示波器看波形,逐步减小死区时间
  • 量产阶段:留20%-30%的余量,考虑温度和老化的影响

3.5 常见问题与排查

现象 可能原因 排查方法
上电就烧MOS管 死区时间过短或未设置 检查BDTR寄存器,用示波器看上下管栅极波形
电机噪音大 死区时间过长 减小死区时间,观察电流波形是否连续
电机转不起来 PWM频率太低或占空比太小 检查ARR和CCR值,确认MOE位已使能
电机发热严重 直通或PWM频率不合适 用电流探头测母线电流,检查死区时间

记住:H桥驱动没有“差不多就行”。死区时间差一点,结果就是炸管和不炸管的区别。我吃过这个亏,希望你不用再吃一次。