电机驱动深度解析:H桥、PWM调速与堵转保护实战指南
👁 8 阅读 · 2026-08-20 · 嵌入式 电机
电机驱动是嵌入式系统的核心应用之一,涉及功率电子、PWM控制与安全保护。本文从H桥拓扑原理出发,剖析其工作模式与死区时间设计,详解PWM调速的实现机制,并针对电机堵转这一常见故障,给出基于电流检测的软硬件保护方案。通过STM32实战代码,演示如何构建一个具备过流保护、堵转检测与自动恢复的直流电机驱动器,帮助开发者提升系统的可靠性与安全性。
## 引言
在嵌入式系统中,电机驱动无处不在:从机器人关节到工业传送带,从无人机螺旋桨到智能家居门窗。然而,驱动电机远不止“给电就转”那么简单。H桥的拓扑选择、PWM的占空比与频率设计、以及堵转时的电流冲击,都是决定系统稳定性的关键。本文将以直流有刷电机为例,深入讲解H桥原理、PWM调速方法,并重点探讨堵转保护的实现策略,提供一套可落地的STM32代码方案。
## H桥:电机换向的基石
### 拓扑与工作原理
H桥由四个开关管(MOSFET或IGBT)组成,形似字母“H”,电机接在桥臂中点。通过控制四个开关的通断组合,可实现电机的正转、反转、制动和滑行:
- **正转**:Q1和Q4导通,Q2和Q3关断,电流从左向右流过电机。
- **反转**:Q2和Q3导通,Q1和Q4关断,电流反向。
- **制动**:Q1和Q3导通(或Q2和Q4),电机两端短路,产生反向电动势制动。
- **滑行**:所有开关关断,电机自由旋转。
实际应用中,常用半桥驱动芯片(如IR2104)配合N-MOSFET,简化逻辑控制。
### 死区时间:防止直通短路
若同一桥臂的上下管同时导通,电源将被短路,烧毁器件。因此,在切换开关状态时,必须插入“死区时间”(Dead Time),即先关闭上管,延迟一段时间后再打开下管。死区时间通常为几百纳秒到几微秒,由驱动芯片或软件定时器实现。
```c
// 示例:使用定时器产生带死区的互补PWM(STM32高级定时器)
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
// 配置定时器1为PWM模式1,输出比较通道1和通道1N互补
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 占空比50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 设置死区时间:例如1us(假设时钟72MHz,死区寄存器值=72)
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 72; // 1us
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRInit(TIM1, &TIM_BDTRInitStructure);
```
## PWM调速:从占空比到有效电压
### 原理与频率选择
PWM(脉宽调制)通过改变占空比来调节电机两端的平均电压,从而控制转速。占空比D = Ton / T,有效电压V_avg = D * V_supply。
- **频率选择**:过低(<1kHz)会导致电机振动和噪声;过高(>50kHz)会增加开关损耗。常用范围:10kHz-20kHz(避开人耳敏感区)。
- **分辨率**:8位(0-255)或16位(0-65535),根据调速精度需求选择。
### 软件实现要点
- 使用定时器产生固定频率的PWM,通过修改比较寄存器更新占空比。
- 避免在中断中频繁修改占空比,可采用双缓冲或DMA。
- 启动时逐渐增加占空比(软启动),防止电流冲击。
```c
// STM32定时器2通道1输出PWM,频率10kHz,占空比可调
void PWM_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InitStructure.TIM_Prescaler = 72 - 1; // 72MHz/72 = 1MHz
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStructure.TIM_Period = 100 - 1; // 1MHz/100 = 10kHz
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void Set_Motor_Speed(uint8_t duty) {
TIM_SetCompare1(TIM2, duty); // duty范围0-100
}
```
## 堵转保护:电流检测与响应策略
### 堵转的危害
当电机负载过大或转子卡死时,转速为零,反电动势消失,电流急剧上升(可达额定电流的5-10倍),导致绕组过热烧毁,或损坏驱动MOSFET。因此,堵转保护是电机驱动系统的必备功能。
### 硬件方案:采样电阻与比较器
- 在电机回路中串联低阻值采样电阻(如0.1Ω),通过差分放大器放大电压,送入ADC或比较器。
- 使用比较器设定阈值,一旦超过立即触发中断,关闭PWM输出。
### 软件方案:ADC采样与状态机
软件方案更灵活,可设置不同阈值和响应时间。核心逻辑:
1. 周期性采样电流(如每1ms)。
2. 若电流超过阈值(如额定电流的1.5倍),启动计时器。
3. 若持续超限超过设定时间(如100ms),判定为堵转,关闭PWM并置位故障标志。
4. 可配置自动恢复:延时后重新尝试启动,若再次堵转则彻底停机。
```c
// 堵转检测状态机示例
#define CURRENT_THRESHOLD 1500 // 电流ADC值阈值
#define BLOCK_TIME_MS 100 // 堵转判定时间
#define RETRY_DELAY_MS 2000 // 重试延时
typedef enum {
MOTOR_RUNNING,
MOTOR_BLOCKED,
MOTOR_RETRY
} MotorState;
MotorState state = MOTOR_RUNNING;
uint16_t block_timer = 0;
uint16_t retry_timer = 0;
void Motor_Protection_Task(void) {
uint16_t current = ADC_GetValue(); // 读取电流采样
switch(state) {
case MOTOR_RUNNING:
if (current > CURRENT_THRESHOLD) {
block_timer++;
if (block_timer >= BLOCK_TIME_MS) {
state = MOTOR_BLOCKED;
PWM_Disable(); // 关闭PWM
Motor_Stop();
// 记录故障日志
}
} else {
block_timer = 0;
}
break;
case MOTOR_BLOCKED:
// 等待重试延时
retry_timer++;
if (retry_timer >= RETRY_DELAY_MS) {
retry_timer = 0;
state = MOTOR_RETRY;
PWM_Enable();
Set_Motor_Speed(30); // 低速重试
}
break;
case MOTOR_RETRY:
// 检查是否恢复正常
if (current < CURRENT_THRESHOLD) {
state = MOTOR_RUNNING;
Set_Motor_Speed(target_speed); // 恢复目标速度
} else {
// 再次堵转,停止重试
state = MOTOR_BLOCKED;
PWM_Disable();
// 设置永久故障标志
}
break;
}
}
```
### 注意事项
- **采样滤波**:电流信号可能含有噪声,需进行软件滤波(如滑动平均)或硬件RC滤波。
- **阈值设定**:需考虑电机启动时的浪涌电流,通常启动时允许短暂过流,因此堵转判定需有延时。
- **热保护**:除电流外,可结合MOSFET温度传感器,实现双重保护。
- **安全冗余**:硬件比较器作为第一道防线,软件作为第二道,防止MCU死机时失控。
## 完整示例:集成H桥与堵转保护
以下代码演示了基于STM32F103的完整驱动流程:初始化PWM和ADC,主循环中执行堵转检测。
```c
int main(void) {
// 初始化系统时钟、GPIO、定时器、ADC等
SystemInit();
PWM_Init();
ADC_Init();
// 设置目标速度(占空比60%)
Set_Motor_Speed(60);
while (1) {
Motor_Protection_Task(); // 每1ms调用一次(可用定时器中断)
// 其他任务...
}
}
```
## 总结
电机驱动看似简单,实则涉及功率电子、控制算法与保护机制。H桥的死区设计是硬件基础,PWM的频率与占空比决定调速性能,而堵转保护则关乎系统安全。本文提供的方案可直接应用于实际项目,但需根据具体电机参数和电源环境调整阈值与延时。建议开发者先在仿真环境中验证逻辑,再上电测试,并逐步优化保护策略。
掌握这些核心要点,你就能构建一个既高效又可靠的电机驱动系统,为你的嵌入式项目增添动力。