4、电机驱动原理:H桥电路详解、直流电机正反转与调速原理、PWM基础知识
好,咱们进入第四章。前面几章我们把 GPIO 和 UART 的基础打牢了,现在终于要碰电机了。说实话,电机驱动是嵌入式开发里最容易出“烟火表演”的环节——我早年就烧过好几个驱动芯片,那味道,记忆犹新。
这一章的核心就三件事:H桥怎么让电机转起来、怎么让它反转、怎么用PWM调速。说白了,就是控制电机的“方向”和“速度”。
4.1 H桥电路详解
直流电机最简单的玩法:给电就转,断电就停。但你要让它反转怎么办?换电源极性。可单片机不能直接换极性啊,这时候就需要 H 桥了。
H桥的名字很形象——四个开关管(通常是 MOSFET 或三极管)搭成一个“H”形状,电机接在中间横杠上。
核心思想:通过控制四个开关的通断组合,改变流过电机的电流方向,从而控制正反转。
4.1.1 基本结构
一个标准的 H 桥由四个开关管组成:
- Q1(左上)、Q2(右上)——高端开关,接电源正极
- Q3(左下)、Q4(右下)——低端开关,接电源负极(GND)
- 电机接在 Q1/Q3 连接点和 Q2/Q4 连接点之间
下面这张图把 H 桥的结构和四种工作状态都画出来了,建议你多看两眼。
4.1.2 四种工作状态
H桥有四种基本状态,我整理成了一张表,方便你对照:
| 状态 | 导通的开关 | 电流方向 | 电机行为 |
|---|---|---|---|
| 正转 | Q1 + Q4 | 左 → 右 | 正向旋转 |
| 反转 | Q2 + Q3 | 右 → 左 | 反向旋转 |
| 刹车 | Q3 + Q4 | 无(短接) | 急停 |
| 惰行 | 全部关断 | 无 | 自由停止 |
致命陷阱:直通(Shoot-Through)
我曾经调试一个电机驱动板,上电瞬间芯片直接冒烟。查了半天,发现是软件里 Q1 和 Q2 同时导通了——电源正极直接对地短路,电流瞬间几十安培。记住:同一侧的上下管绝对不能同时导通。切换方向时,必须先关断所有开关,留一个“死区时间”,再打开另一组。
4.2 直流电机正反转与调速原理
有了 H 桥,正反转就很简单了。但调速呢?直流电机的转速和两端电压成正比——电压越高,转得越快。可单片机只能输出 0V 或 3.3V/5V,怎么调出中间电压?
答案就是:PWM(脉冲宽度调制)。
4.2.1 PWM 基础知识
PWM 说白了就是“快速开关电源”。你以很高的频率(比如 1kHz)不停地开、关,电机由于机械惯性,不会跟着每个脉冲抖动,而是感受到一个“平均电压”。
举个例子:
- 5V 电源,50% 时间开,50% 时间关 → 平均电压 ≈ 2.5V
- 5V 电源,80% 时间开,20% 时间关 → 平均电压 ≈ 4.0V
这个“开的时间比例”就叫占空比(Duty Cycle)。
核心公式:
平均电压 = 电源电压 × 占空比
占空比 = 高电平时间 / (高电平时间 + 低电平时间) × 100%
4.2.2 关键参数
| 参数 | 说明 | 典型值 |
|---|---|---|
| 频率 | 每秒开关次数 | 1kHz ~ 20kHz |
| 周期 | 一次开关的总时间 | 1ms(1kHz时) |
| 占空比 | 高电平时间占比 | 0% ~ 100% |
| 分辨率 | 占空比可调节的步进数 | 8位(256级)或16位(65536级) |
频率怎么选?
我个人习惯:
- 普通直流电机:1kHz ~ 5kHz 就够了,频率太低电机会“咔咔”响
- 带减速箱的电机:可以低一些,500Hz ~ 1kHz
- 有刷电机:超过 20kHz 人耳听不到,但开关损耗会增加
我在一个项目中用过 50Hz 的 PWM,结果电机像在打拍子,嗡嗡响得头疼。后来改到 2kHz,世界清净了。
4.2.3 用 PWM 控制电机转速
结合 H 桥和 PWM,我们就可以同时控制方向和速度了:
- 方向控制:通过 H 桥的开关组合决定
- 速度控制:对导通的那一组开关管施加 PWM 信号
举个例子,正转调速:
- Q1 和 Q4 导通,但 Q1 的栅极接 PWM 信号
- 占空比 100% → 全速正转
- 占空比 50% → 半速正转
- 占空比 0% → 停止
反转同理,把 PWM 加到 Q2 或 Q3 上就行。
4.3 实战:用 STM32 输出 PWM 控制电机
理论说完了,来点实际的。下面是一个用 STM32 定时器输出 PWM 的代码片段,控制电机正转并调速。
// 使用 TIM2 的通道1(PA0)输出 PWM
// 配置:频率 1kHz,占空比 50%
void Motor_PWM_Init(void) {
// 1. 使能定时器和GPIO时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 2. 配置 PA0 为复用功能(AF2 = TIM2_CH1)
GPIOA->MODER &= ~(3 << 0); // 清零
GPIOA->MODER |= (2 << 0); // 复用功能模式
GPIOA->AFR[0] &= ~(0xF << 0);
GPIOA->AFR[0] |= (1 << 0); // AF1 = TIM2
// 3. 配置定时器
TIM2->PSC = 83; // 预分频:84MHz / (83+1) = 1MHz
TIM2->ARR = 999; // 自动重装:1MHz / (999+1) = 1kHz
TIM2->CCR1 = 500; // 占空比:500 / 1000 = 50%
// 4. 配置 PWM 模式1
TIM2->CCMR1 &= ~(7 << 4); // 清零 OC1M
TIM2->CCMR1 |= (6 << 4); // PWM 模式1
TIM2->CCER |= TIM_CCER_CC1E; // 使能输出
// 5. 启动定时器
TIM2->CR1 |= TIM_CR1_CEN;
}
// 调速函数
void Motor_SetSpeed(uint16_t duty) {
if(duty > 1000) duty = 1000; // 限制范围
TIM2->CCR1 = duty; // 更新占空比
}
避坑指南:
我曾经在调试时发现电机转速不稳,用示波器一看,PWM 波形偶尔会“丢脉冲”。查了半天,原来是定时器中断优先级太低,被其他中断打断了。解决办法:把定时器更新中断优先级设高,或者干脆不用中断,只靠硬件自动输出。
4.4 常见问题与注意事项
最后总结几个我踩过的坑:
- 电机启动电流很大:堵转时电流可能是额定电流的 5~10 倍。选驱动芯片时一定要留余量,别卡着额定值选。
- 续流二极管不能省:电机是感性负载,关断时会产生反向电动势。不加续流二极管,电压尖峰能击穿 MOSFET。
- PWM 频率别太低:低于 100Hz 电机就会“步进式”转动,噪音大、抖动厉害。
- 死区时间要留够:切换方向时,先关断所有开关,等几十微秒再打开另一组。我一般设 1~5μs。
安全第一:
电机驱动电路调试时,手边一定要放个急停开关。我第一次做电机驱动时,程序跑飞了,电机直接全速撞到限位块,把机械结构都撞坏了。从那以后,我所有电机项目都会加硬件急停和软件看门狗。