3. STM32基础开发:开发环境搭建与核心外设
各位同学,欢迎来到《Rover差速转向底盘驱动开发实战》的第三讲。今天我们要聊的,是STM32开发中最基础、也最绕不开的几个环节:环境搭建、GPIO、PWM和中断。别小看这些内容,我当年刚入行时,就是在这几个地方栽过跟头。咱们一个一个来拆解。
3.1 开发环境搭建:Keil与CubeMX的配合
做STM32开发,我个人习惯用两套工具配合:STM32CubeMX 负责图形化配置,Keil MDK 负责写代码和调试。说白了,CubeMX帮你生成初始化代码,Keil让你在代码里“折腾”。
第一步:安装Keil MDK
去Keil官网下载MDK-ARM版本,安装时注意选对芯片包。我建议你直接装最新版,省得后面遇到兼容性问题。安装完成后,记得用管理员权限打开一次,否则有些驱动会装不上。
第二步:安装STM32CubeMX
这个工具是ST官方的,免费。下载后直接安装,它会自动识别你电脑上的Keil版本。嗯,这里有个坑:如果你先装CubeMX后装Keil,CubeMX可能找不到Keil路径。解决办法很简单——重装CubeMX,或者手动指定Keil路径。
第三步:生成工程
打开CubeMX,选择你的芯片型号(比如我们常用的STM32F103C8T6)。配置好时钟、外设后,点击“Project -> Generate Code”。生成时选“MDK-ARM”工具链,版本选V5。这样生成的工程,直接用Keil打开就能编译。
3.2 GPIO配置:从点灯到控制电机
GPIO是STM32最基础的外设。说白了,它就是芯片的“手脚”,用来输出高低电平或读取外部信号。在底盘驱动中,GPIO主要用来控制电机方向、读取编码器信号。
GPIO的几种模式
| 模式 | 用途 | 典型场景 |
|---|---|---|
| 推挽输出 | 输出高低电平 | 控制电机方向引脚 |
| 开漏输出 | 需要外部上拉 | I2C通信 |
| 浮空输入 | 读取外部电平 | 按键检测 |
| 上拉/下拉输入 | 带内部电阻的输入 | 编码器信号读取 |
配置示例:控制电机方向
假设我们用PA0和PA1控制左电机的正反转。在CubeMX里,把这两个引脚配置为“GPIO_Output”,然后在代码里这样写:
// 左电机正转
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 方向1
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 方向2
// 左电机反转
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
3.3 定时器PWM输出:让电机转起来
PWM(脉宽调制)是控制电机速度的核心手段。说白了,就是通过调整高电平占空比,来改变电机两端的平均电压。STM32的定时器可以输出多路PWM,非常适合驱动差速底盘的两个电机。
PWM配置步骤
- 在CubeMX里选择一个定时器(比如TIM2),配置为“内部时钟”
- 设置预分频器(PSC)和自动重装载值(ARR),决定PWM频率
- 使能某个通道(比如CH1),模式选“PWM Generation CH1”
- 设置初始占空比(比如50%)
代码示例:动态调整占空比
// 初始化PWM
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
// 设置占空比为75%
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 750);
// 设置占空比为25%
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 250);
你想想看,差速转向的核心就是左右轮速度不同。左轮PWM占空比大,右轮小,车子就往右转。这个逻辑,说白了就是靠PWM实现的。
3.4 中断系统:让CPU“偷懒”
中断是嵌入式系统的灵魂。没有中断,CPU就得一直轮询检查各种事件,效率极低。有了中断,CPU可以该干嘛干嘛,等事件发生了再“被叫醒”。
中断优先级
STM32的中断有抢占优先级和子优先级。抢占优先级高的中断,可以打断正在执行的低优先级中断。在底盘驱动中,我建议把电机控制中断设为高优先级,把通信中断设为低优先级。
配置示例:外部中断读取编码器
编码器每转一圈会产生多个脉冲。我们用外部中断来捕获这些脉冲,从而计算电机转速。
// 在CubeMX中配置PA0为外部中断线0,下降沿触发
// 然后在stm32f1xx_it.c中编写中断服务函数
void EXTI0_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
{
// 编码器脉冲计数加1
encoder_count++;
// 清除中断标志位
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
}
}
3.5 本章知识体系
为了让你更直观地理解本章内容,我画了一张结构图。它展示了开发环境、GPIO、PWM和中断之间的关系,以及它们在底盘驱动中的位置。
这张图把本章内容串起来了。你从环境搭建开始,一步步配置GPIO、PWM和中断,最后就能让电机按照你的指令转动。说白了,这就是底盘驱动的基础骨架。
公众号:蓝海资料掘金营,微信deep3321