直流有刷电机的运转本质上是电磁感应现象的具体应用。理解电机工作原理需要掌握两个基本电磁学定律:
左手定则(电动机定则):用于判断通电导体在磁场中的受力方向。具体操作为:
右手定则(发电机定则):用于判断导体切割磁感线时产生的感应电流方向。这个定则在电机作为发电机使用时尤为重要。
在实际电机设计中,转子上通常布置多组线圈(称为电枢绕组),配合换向器和电刷实现持续旋转。这种设计解决了单线圈电机的几个关键问题:
专业提示:现代直流有刷电机通常采用斜槽设计(转子铁芯槽与轴线呈一定角度),这能进一步减小转矩脉动,使运行更加平稳。
典型直流有刷电机包含以下核心部件:
定子组件:
转子组件:
辅助部件:

表:直流有刷电机主要参数说明
| 参数 | 典型值 | 说明 |
|---|---|---|
| 额定电压 | 6-24V | 工作电压范围 |
| 空载转速 | 3000-10000rpm | 无负载时的最高转速 |
| 堵转电流 | 0.5-5A | 转子堵转时的电流 |
| 额定转矩 | 0.01-0.5N·m | 连续工作允许输出转矩 |
H桥电路因其拓扑结构形似字母"H"而得名,是控制直流电机最常用的驱动电路。基本H桥由四个开关管(MOSFET或晶体管)组成,通过不同开关组合实现电机正反转和制动控制。
典型工作状态:
正转模式:
反转模式:
制动模式:
自由停止:

H桥电路设计中最危险的问题是直通短路(Shoot-through),即同一桥臂上下管同时导通造成的电源直接短路。为防止这种情况,必须实现以下保护措施:
死区时间控制:
互锁逻辑:
栅极驱动设计:
表:常见H桥驱动芯片对比
| 型号 | 最大电压 | 峰值电流 | 集成度 | 特点 |
|---|---|---|---|---|
| L298N | 46V | 2A | 双H桥 | 经济实用,需外接续流二极管 |
| TB6612 | 15V | 1.2A | 双H桥 | 低功耗,内置保护电路 |
| DRV8833 | 11V | 1.5A | 双H桥 | 小封装,低导通电阻 |
| VNH5019 | 41V | 30A | 单H桥 | 大电流,集成电流检测 |
实践建议:对于STM32项目,推荐使用TB6612或DRV8833这类集成驱动芯片,它们体积小、外围电路简单,且内置了必要的保护功能。
STM32系列单片机提供了丰富的外设资源用于电机控制,合理配置这些资源对系统性能至关重要:
定时器选择:
GPIO配置:
ADC应用:

使用STM32高级定时器(如TIM1/TIM8)生成带死区的PWM波时,需要特别注意以下配置步骤:
时钟配置:
c复制RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
时基初始化:
c复制TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 999; // PWM周期= (999+1)/72MHz = 13.89us (72kHz)
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 无分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
PWM输出配置:
c复制TIM_OCInitTypeDef TIM_OCInitStructure;
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_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
死区时间设置:
c复制TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = 0x54; // 约1us死区时间
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
使能定时器:
c复制TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
调试技巧:使用STM32CubeMX工具可以直观地配置定时器参数并生成初始化代码,大大简化开发流程。但要注意检查生成的死区时间是否满足驱动芯片要求。
直流电机常用的位置/速度传感器主要有两种类型:
光电编码器:
霍尔编码器:

STM32的定时器编码器接口模式可以高效处理正交编码器信号,典型配置步骤如下:
GPIO初始化:
c复制GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
定时器编码器模式配置:
c复制TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising);
TIM_SetCounter(TIM3, 0);
TIM_Cmd(TIM3, ENABLE);
速度计算算法:
c复制int32_t GetSpeedRPM(void)
{
static int32_t last_count = 0;
int32_t current_count = TIM_GetCounter(TIM3);
int32_t delta = current_count - last_count;
last_count = current_count;
// 假设编码器100PPR,4倍频,减速比30
// 每转脉冲数 = 100×4 = 400
// 电机转数 = delta / (400×30)
float rpm = (delta * 60.0f) / (400.0f * 30.0f); // 转换为RPM
return (int32_t)rpm;
}
基于PID的速度控制算法实现要点:
PID参数结构体:
c复制typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float integral; // 积分项
float prev_err; // 上次误差
float max_out; // 输出限幅
} PID_Controller;
PID计算函数:
c复制float PID_Compute(PID_Controller* pid, float setpoint, float feedback)
{
float error = setpoint - feedback;
// 比例项
float P = pid->Kp * error;
// 积分项(抗饱和处理)
pid->integral += error;
if(pid->integral > pid->max_out) pid->integral = pid->max_out;
if(pid->integral < -pid->max_out) pid->integral = -pid->max_out;
float I = pid->Ki * pid->integral;
// 微分项
float D = pid->Kd * (error - pid->prev_err);
pid->prev_err = error;
// 总和输出
float output = P + I + D;
if(output > pid->max_out) output = pid->max_out;
if(output < -pid->max_out) output = -pid->max_out;
return output;
}
速度控制任务:
c复制void SpeedControlTask(void)
{
static PID_Controller speed_pid = {
.Kp = 0.5f,
.Ki = 0.1f,
.Kd = 0.01f,
.max_out = 100.0f
};
int32_t actual_speed = GetSpeedRPM();
float pwm = PID_Compute(&speed_pid, target_speed, actual_speed);
// 更新PWM输出
if(pwm >= 0) {
SetDirection(FORWARD);
SetPWM((uint32_t)fabs(pwm));
} else {
SetDirection(BACKWARD);
SetPWM((uint32_t)fabs(pwm));
}
}
调试经验:PID参数整定应遵循"先P后I最后D"的原则。初始调试时先将Ki和Kd设为0,逐渐增大Kp直到系统出现等幅振荡,然后取该值的50%作为最终Kp。Ki一般取Kp的1/10到1/5,Kd取Kp的1/100到1/50。
电源设计:
信号隔离:
散热设计:
表:直流电机控制系统常见问题及解决方法
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 电机不转 | 电源未接通 | 检查电源指示灯 |
| 使能信号无效 | 测量EN引脚电平 | |
| PWM信号异常 | 用示波器检查PWM输出 | |
| 电机单向转动 | H桥一侧损坏 | 交换IN1/IN2测试 |
| 方向信号固定 | 检查GPIO配置 | |
| 转速不稳定 | PID参数不当 | 重新整定PID |
| 编码器信号干扰 | 检查屏蔽和接地 | |
| 电机发热严重 | 负载过大 | 检查机械传动 |
| PWM频率过低 | 提高至15kHz以上 | |
| 驱动芯片发烫 | 死区时间不足 | 增加死区时间 |
| 散热不足 | 添加散热片 |
磁场定向控制(FOC):
参数自动整定:
网络化控制:
能量回馈设计:
在实际项目中,我发现电机控制系统的稳定性很大程度上取决于电源质量。一个实用的技巧是在电源输入端增加一个共模扼流圈,能有效抑制电机产生的电源干扰。另外,对于长时间运行的设备,建议定期检查电刷磨损情况,这往往是导致性能下降的首要原因。