一、初识STM32与电机控制
各位同学,欢迎来到这门实战课。我是你们的老朋友,一个在电机控制领域摸爬滚打了十几年的工程师。
说实话,电机控制这个方向,入门容易,精通难。但只要你把基础打牢了,后面那些复杂的算法、调试技巧,其实都是水到渠成的事。今天这一章,我们就从最根本的东西聊起。
1.1 STM32在电机控制领域的地位
为什么市面上那么多MCU,偏偏STM32成了电机控制的主流选择?我个人觉得,核心原因有三个:
- 硬件外设强大:高级定时器、ADC、DAC、比较器,这些电机控制需要的“硬家伙”,STM32基本都给你配齐了。
- 生态成熟:从HAL库到CubeMX,从MCSDK到各种开源方案,你几乎能找到所有电机控制场景的参考代码。
- 性价比高:从F1到G4,从H7到U5,总有一款适合你的成本和性能要求。
核心观点:STM32不是唯一的电机控制MCU,但它绝对是让你“少走弯路”的那一个。我在项目中用过DSP、用过其他ARM核的片子,最后发现,STM32的文档和社区支持,能帮你省下至少30%的开发时间。
1.2 三种常见电机的基本原理
做电机控制,你得先知道你在控制什么。这里我简单梳理一下三种最常见的电机类型,它们的原理和特点。
| 电机类型 | 基本原理 | 控制方式 | 典型应用 |
|---|---|---|---|
| 直流电机 | 电刷换向,通电线圈在磁场中受力旋转 | 调电压/PWM调速 | 玩具、电动工具、车窗升降 |
| 步进电机 | 定子绕组通电顺序决定转子步进角度 | 脉冲+方向控制 | 3D打印机、数控机床、机械臂 |
| 无刷电机(BLDC) | 电子换向,永磁转子跟随定子旋转磁场 | 六步换向/FOC | 无人机、电动车、家电变频 |
我的经验:初学者最容易搞混的是步进电机和BLDC。步进电机是开环控制,你给它发多少个脉冲,它就转多少步;BLDC是闭环控制,你得实时知道转子的位置,才能正确换向。嗯,这个区别很重要,后面章节我们会反复提到。
1.3 搭建第一个电机控制工程
理论说完了,咱们直接上手。这一节的目标很简单:用STM32的定时器输出PWM,点亮一个LED,模拟电机控制中的PWM输出过程。
你可能会问:“点亮LED跟电机控制有什么关系?”
关系大了。电机控制的核心就是PWM。你给电机绕组的电压,本质上就是一组PWM波形。LED的亮度变化,其实就是PWM占空比的变化。把这个搞懂了,后面控制电机转速、电流,都是同一个道理。
1.3.1 硬件准备
- STM32开发板一块(我这里用STM32F103C8T6,俗称“蓝色药丸”)
- 一个LED(板载或外接都行)
- 一个220Ω限流电阻
- 杜邦线若干
1.3.2 软件配置(CubeMX)
- 打开STM32CubeMX,新建工程,选择你的芯片型号。
- 配置时钟源:HSE(外部晶振)或HSI(内部时钟)都行,我习惯用HSE,精度更高。
- 配置定时器:选择TIM2,通道1(CH1)作为PWM输出。
- 设置定时器参数:
- 预分频器(Prescaler):71(72MHz时钟,分频后为1MHz)
- 自动重装载值(Counter Period):999(PWM频率 = 1MHz / 1000 = 1kHz)
- 脉冲值(Pulse):500(初始占空比50%)
- 配置GPIO:将TIM2_CH1对应的引脚(PA0)设置为推挽输出。
- 生成代码(选择MDK-ARM或STM32CubeIDE)。
注意:定时器的时钟源一定要确认清楚。我曾经在一个项目里,因为APB1和APB2的时钟配置搞混了,导致PWM频率算出来差了一倍,查了整整一个下午。嗯,这种坑,踩过一次就记住了。
1.3.3 代码实现
在生成的main.c文件中,添加以下代码:
/* 在main函数中 */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
/* 启动PWM输出 */
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
uint16_t duty = 0;
uint8_t dir = 1;
while (1)
{
/* 呼吸灯效果:占空比从0到999循环 */
if (dir)
{
duty += 10;
if (duty >= 999) dir = 0;
}
else
{
duty -= 10;
if (duty <= 0) dir = 1;
}
/* 设置占空比 */
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty);
HAL_Delay(10);
}
}
小技巧:__HAL_TIM_SET_COMPARE这个宏,其实就是直接写定时器的CCR寄存器。你如果对寄存器操作熟悉,也可以直接写 TIM2->CCR1 = duty;,效果一样,但速度更快。
1.4 本章知识体系
为了让你更直观地理解这一章的内容结构,我画了一张图。你可以把它当作一个“知识地图”,后面每学完一章,都可以回来对照一下。
1.5 避坑指南
最后,分享几个我当年踩过的坑,希望能帮你省点时间:
- 定时器配置不对:PWM频率算错了,电机要么嗡嗡响,要么根本不转。记住公式:
PWM频率 = 定时器时钟 / (Prescaler + 1) / (Counter Period + 1)。 - GPIO复用功能没开:定时器的PWM输出引脚,必须配置为复用功能(AF),否则输出的是普通GPIO电平,不是PWM波形。
- 占空比范围搞错:CCR寄存器的值不能超过ARR(自动重装载值),否则PWM波形会异常。我见过有人把CCR设成了2000,ARR是999,结果输出全高电平,还以为是芯片坏了。
曾经有一次,我在调试一个BLDC驱动板时,电机死活转不起来。查了三天,最后发现是定时器的时钟源选错了——用了内部LSI,频率只有40kHz,根本不够驱动电机。从那以后,我每次建工程第一件事就是确认时钟树。嗯,这个习惯救了我很多次。
好了,这一章的内容就到这里。你只要把PWM的原理和配置搞明白,后面那些FOC、六步换向、电流环,其实都是在这个基础上加东西。别急,我们一步一步来。