第二章 开发环境搭建:Keil/STM32CubeIDE安装、工程模板创建、GPIO与PWM外设初始化

好,咱们正式开始动手了。这一章,说白了就是磨刀。刀磨快了,后面砍柴才不费劲。我见过不少新手,上来就急着写算法,结果环境没配好,一个编译错误卡半天,心态直接崩了。咱们别干那傻事。

2.1 开发工具的选择:Keil还是STM32CubeIDE?

这个问题,几乎每个初学者都会问。我的答案是:两个都要会,但初期建议从STM32CubeIDE入手

为什么?因为STM32CubeIDE是ST官方出的,免费,而且集成了CubeMX图形化配置工具。你想想看,配置时钟树、GPIO、定时器这些,点点鼠标就能生成初始化代码,多省心。我个人习惯用CubeIDE做项目的前期配置和调试,效率确实高。

那Keil呢?Keil MDK是老牌工具,生态成熟,很多企业项目都在用。但它是收费的,虽然有代码大小限制的免费版(32KB),做咱们这个按摩仪项目也够用。不过,我建议你直接上STM32CubeIDE,省去破解的麻烦。

我的小建议: 如果你以后打算去大厂做嵌入式开发,Keil还是得学。但现阶段,咱们用CubeIDE,把精力放在算法本身。

2.2 安装STM32CubeIDE(手把手版)

安装过程其实没啥技术含量,但有几个坑我得提前跟你说。

  1. 去官网下载: 搜索“STM32CubeIDE”,找到ST官网的下载页面。别去第三方网站下,容易中招。
  2. 版本选择: 下载最新稳定版就行。我当时装的是1.13.0,现在可能更新了,无所谓。
  3. 安装路径: 路径不要有中文!不要有空格!我见过有人装在“D:\软件\STM32CubeIDE”,结果编译报错,查了半天是路径问题。老老实实用英文路径。
  4. 安装组件: 安装过程中会提示你选择要支持的芯片系列。咱们做按摩仪,用STM32F103系列,所以把F1系列勾上就行。其他的暂时用不到,以后需要再装。
注意: 安装过程中会联网下载一些固件包,如果你的网络不好,可能会很慢。我曾经在客户现场,网络差得要命,装了一个下午。建议提前下载好离线包,或者找个网络好的地方。

2.3 创建你的第一个工程模板

安装好了,咱们来建个工程。这一步很关键,因为后面所有章节的代码,都会基于这个模板。

打开STM32CubeIDE,点击 File > New > STM32 Project。在芯片选择界面,输入“STM32F103C8T6”,选中它,点Next。给工程起个名字,比如“MassageChair_MotorCtrl”,点Finish。

这时候,CubeMX的图形化界面就打开了。你会看到一个芯片的引脚图。别慌,咱们一步步来。

2.3.1 配置时钟树(RCC)

时钟是芯片的心脏。配置不对,外设跑不起来。咱们按摩仪电机控制,需要比较精准的PWM波形,所以时钟要配好。

  • Pinout & Configuration 标签页,找到 RCC,把 High Speed Clock (HSE) 设置为 Crystal/Ceramic Resonator。咱们板子上一般有个8MHz的晶振。
  • 切换到 Clock Configuration 标签页。这里就是时钟树了。把 HSE 设为8MHz,然后配置PLL,让系统时钟 SYSCLK 跑到72MHz。具体操作:在 HCLK 输入框里输入72,回车,软件会自动帮你算好分频系数。
核心要点: 系统时钟72MHz,APB1总线时钟36MHz(因为定时器挂在这条总线上),APB2总线时钟72MHz。这个配置,咱们后面写PWM时会用到。

2.3.2 配置GPIO

GPIO就是芯片的引脚。咱们按摩仪需要控制电机,那肯定要输出PWM信号。我习惯用定时器的PWM输出功能,这样不占CPU。

假设咱们用定时器TIM2的通道1输出PWM,对应的引脚是PA0。在引脚图上找到PA0,右键,选择 TIM2_CH1。然后,在左侧的 Timers 菜单里,找到 TIM2,把 Channel1 设置为 PWM Generation CH1

嗯,这里要注意,GPIO的模式要配成 Alternate Function Push-Pull(复用推挽输出),速度选 High。这样PWM信号才能快速翻转。

2.3.3 配置PWM参数

PWM有两个关键参数:频率和占空比。频率决定了电机转动的细腻程度,占空比决定了电机的速度。

在TIM2的 Parameter Settings 里,咱们来算一下:

  • Prescaler (PSC): 预分频器。假设咱们想要PWM频率为20kHz(20,000Hz),那么PSC+1 = 72MHz / (20,000 * (ARR+1))。咱们先设PSC=71,也就是72分频,那么定时器时钟就变成了1MHz。
  • Counter Period (ARR): 自动重装载值。ARR+1 = 1MHz / 20kHz = 50。所以ARR=49。
  • Pulse: 这就是占空比了。比如设成25,那么占空比就是25/50 = 50%。

你看,算起来很简单。我刚开始学的时候,总是搞混PSC和ARR的关系。后来我总结了一句话:PSC决定计数速度,ARR决定计数范围。你想想看,是不是这个理?

// 代码示例:PWM初始化(由CubeMX自动生成,但你要理解)
// 这段代码在 tim.c 里

void MX_TIM2_Init(void)
{
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 71;          // 72分频,定时器时钟1MHz
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 49;             // ARR=49,PWM频率20kHz
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 25;               // 初始占空比50%
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
}

2.4 生成代码并验证

配置完成后,点击工具栏上的小锤子图标(Generate Code)。CubeMX会自动帮你生成初始化代码。然后,在 main.cmain() 函数里,加上启动PWM的代码:

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

编译,下载到板子里。用示波器或者逻辑分析仪量一下PA0引脚,你应该能看到一个20kHz的方波。如果没有,检查一下时钟配置和GPIO模式。

避坑指南: 我曾经有一次,怎么调都没波形,折腾了半天,最后发现是示波器的探头没接地。嗯,这种低级错误,谁都会犯,别灰心。

2.5 本章小结

这一章,咱们把开发环境搭好了,也生成了第一个PWM工程模板。你可能会觉得,这不就是点点鼠标吗?没错,但关键是你要理解每一步背后的原理。时钟怎么配的?PWM频率怎么算的?这些基础打牢了,后面写FOC算法、PID控制,你才不会发懵。

下一章,咱们就要开始写真正的电机控制代码了。到时候,这个模板就是咱们的起点。