一、初识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)

  1. 打开STM32CubeMX,新建工程,选择你的芯片型号。
  2. 配置时钟源:HSE(外部晶振)或HSI(内部时钟)都行,我习惯用HSE,精度更高。
  3. 配置定时器:选择TIM2,通道1(CH1)作为PWM输出。
  4. 设置定时器参数:
    • 预分频器(Prescaler):71(72MHz时钟,分频后为1MHz)
    • 自动重装载值(Counter Period):999(PWM频率 = 1MHz / 1000 = 1kHz)
    • 脉冲值(Pulse):500(初始占空比50%)
  5. 配置GPIO:将TIM2_CH1对应的引脚(PA0)设置为推挽输出。
  6. 生成代码(选择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 本章知识体系

为了让你更直观地理解这一章的内容结构,我画了一张图。你可以把它当作一个“知识地图”,后面每学完一章,都可以回来对照一下。

第一章知识体系图 第一章:初识STM32与电机控制 STM32的地位 三种电机原理 第一个工程实践 硬件外设强大 生态成熟 性价比高 直流电机 步进电机 无刷电机(BLDC) CubeMX配置 PWM输出代码 呼吸灯效果 核心逻辑 从了解STM32的优势 → 理解电机原理 → 动手实践PWM输出 这是一个“认知→理解→应用”的完整学习闭环

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、六步换向、电流环,其实都是在这个基础上加东西。别急,我们一步一步来。