1. 直流电机PWM调速系统概述直流电机作为最常用的动力装置之一在机器人、智能小车、工业控制等领域应用广泛。而PWM脉冲宽度调制调速则是控制直流电机转速最经济高效的方式。我刚开始接触电机控制时发现很多教程要么过于理论化要么代码不完整导致实际调试时总是遇到各种问题。经过多个项目的实战积累今天就来分享一套基于STM32的完整解决方案。PWM调速的本质是通过快速切换电源通断用数字信号模拟模拟量控制。举个例子就像用开关水龙头的方式控制平均水流大小——快速交替开关通过调整开的时间比例占空比来控制流速。在电机控制中20%占空比意味着电机只获得20%的全电压功率转速自然比100%占空比时低。这个系统主要包含三个关键部分STM32微控制器负责产生PWM信号电机驱动模块如L298N放大电流驱动电机直流电机执行机构2. 硬件设计详解2.1 核心器件选型我在多个项目中测试过不同配置这里推荐性价比最高的组合STM32F103C8T672MHz主频足够产生稳定的PWM波L298N驱动模块最大支持2A电流内置续流二极管12V直流减速电机带编码器反馈的更佳特别提醒选L298N时要注意散热问题。有次连续工作2小时后模块发烫严重后来加装散热片才解决。驱动大功率电机1A时建议选用带散热片的升级版本。2.2 电路连接要点实际接线时最容易犯的三个错误共地问题必须将STM32的GND与L298N的GND相连电源隔离控制逻辑5V与电机电源12V要分开供电使能端处理ENA/ENB需要接PWM信号不要直接接高电平推荐连接方式STM32 PA8(定时器1通道1) - L298N ENA STM32 PA9/PA10 - L298N IN1/IN2 12V电源正极 - L298N VMS 12V电源负极 - L298N GND3. PWM生成原理与STM32配置3.1 定时器工作原理STM32的定时器就像精密的数字沙漏。以TIM1为例其工作流程为时钟源如72MHz经过预分频器降低频率计数器从0累加到自动重装载值ARR比较寄存器CCR决定PWM占空比当计数器值小于CCR时输出高电平否则输出低电平关键参数计算公式PWM频率 定时器时钟 / [(ARR1)*(PSC1)]占空比 CCR / (ARR1)3.2 代码实现这里给出最精简的配置代码使用HAL库// PWM初始化函数 void PWM_Init(void) { TIM_HandleTypeDef htim1; TIM_OC_InitTypeDef sConfigOC {0}; htim1.Instance TIM1; htim1.Init.Prescaler 71; // 72MHz/72 1MHz htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 999; // 1MHz/1000 1kHz PWM htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(htim1); sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 500; // 初始占空比50% sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim1, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); }实测发现PWM频率选择1kHz-5kHz最为合适。频率太低电机会有啸叫声太高则驱动模块损耗增大。4. 调速系统软件设计4.1 速度控制算法最简单的开环控制可以直接通过调节PWM占空比实现。但想要更精准的控制可以加入PID算法typedef struct { float Kp, Ki, Kd; float error, lastError; float integral, derivative; float output; } PID_Controller; void PID_Update(PID_Controller* pid, float setpoint, float actual) { pid-error setpoint - actual; pid-integral pid-error; pid-derivative pid-error - pid-lastError; pid-output pid-Kp * pid-error pid-Ki * pid-integral pid-Kd * pid-derivative; pid-lastError pid-error; }4.2 完整控制流程一个健壮的调速系统应该包含以下功能电机使能/失能控制方向控制速度设定与反馈过流保护推荐的程序架构while(1) { // 1. 读取速度设定值如电位器或串口命令 speed_set Get_Speed_Setting(); // 2. 获取实际速度编码器反馈 speed_actual Encoder_GetSpeed(); // 3. PID计算 PID_Update(pid, speed_set, speed_actual); // 4. 更新PWM占空比 __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, (uint16_t)pid.output); // 5. 故障检测 if(Overcurrent_Detected()) { Motor_Stop(); break; } }5. 调试技巧与常见问题5.1 示波器使用技巧调试PWM系统时示波器是最得力的工具。重点观察波形频率是否准确占空比变化是否平滑上升/下降沿是否有振铃遇到电机抖动时我的排查步骤通常是先用示波器看PWM信号是否干净检查电源电压是否稳定测量电机电流是否超出驱动能力5.2 典型问题解决方案问题1电机启动困难可能原因启动电流过大解决方案采用软启动策略逐步增加PWM占空比问题2特定转速区间振动明显可能原因机械共振解决方案避开该转速区间或增加减震措施问题3驱动芯片发热严重可能原因开关损耗过大解决方案降低PWM频率或改进散热记得第一次做电机控制时因为没加续流二极管烧毁了三个驱动芯片。后来养成习惯凡是感性负载必加续流保护。这也是为什么推荐使用L298N这类集成驱动模块——它们已经内置了必要的保护电路。