第2章:嵌入式系统基础——STM32微控制器介绍、开发环境搭建与GPIO/定时器

各位同学,欢迎来到嵌入式系统基础这一章。说实话,植保作业路径优化这件事,光有算法是不够的——你得让算法在硬件上跑起来。而STM32,就是我这些年做农业嵌入式项目最常用的平台。没有之一。

2.1 STM32微控制器:为什么选它?

STM32是意法半导体推出的32位ARM Cortex-M系列微控制器。你想想看,一个植保无人机或者农业机器人,需要同时处理GPS数据、控制电机、读取传感器、还要跑路径规划算法——8位单片机根本扛不住。STM32刚好填补了这个空白。

我个人习惯把STM32分成几个系列:

系列 内核 典型应用场景 我常用的型号
F1系列 Cortex-M3 基础控制、传感器采集 STM32F103C8T6
F4系列 Cortex-M4 带DSP、浮点运算,适合路径计算 STM32F407VGT6
F7/H7系列 Cortex-M7 高性能、多任务、实时性要求高 STM32H743
G0/G4系列 Cortex-M0+/M4 低功耗、性价比高 STM32G070

我在项目中遇到过一个问题:用F103做植保机器人的路径规划,结果算一个B样条曲线要卡顿好几秒。后来换成F407,带硬件浮点单元,速度直接提升了5倍。所以选型这事,别省。

核心要点:STM32的优势在于——丰富的外设(GPIO、定时器、ADC、DMA、CAN、I2C、SPI)、成熟的生态(HAL库、LL库、FreeRTOS)、以及极高的性价比。一块F103开发板才几十块钱,但能干的事远超你的想象。

2.2 开发环境搭建:Keil + CubeMX

搭建开发环境,说白了就是三件事:装软件、配工具、跑通第一个程序。我建议你按这个顺序来。

2.2.1 安装Keil MDK

Keil MDK是ARM公司出的IDE,专门用来开发STM32。去官网下载MDK-ARM版本,安装时注意勾选上对应的器件包(Device Family Pack)。

嗯,这里要注意:Keil的License需要购买,但你可以先用评估版(限制代码大小)。我个人建议学生党先用评估版,等真正做项目了再买正版。

2.2.2 安装STM32CubeMX

CubeMX是ST官方出的图形化配置工具。你可以在里面选芯片型号、配置时钟树、设置GPIO、定时器、串口等外设,然后自动生成初始化代码。

我曾经犯过一个低级错误:手动配置时钟树,结果把系统时钟配错了,芯片直接跑不起来。后来老老实实用CubeMX生成,再也没出过问题。所以我的建议是——能用工具生成的,别手写。

2.2.3 第一个工程:点亮LED

咱们来写一个最简单的程序——点亮板子上的LED。这就像学编程的"Hello World"。

步骤是这样的:

  1. 打开CubeMX,选择芯片型号(比如STM32F103C8)
  2. 在Pinout视图中,找到PC13引脚(这是LED对应的引脚)
  3. 设置为GPIO_Output
  4. 配置时钟:HSE 8MHz,系统时钟72MHz
  5. 生成代码(选择MDK-ARM)
  6. 在Keil中打开工程,在main.c里写代码
// main.c 中的主循环
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  while (1)
  {
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    HAL_Delay(500);  // 延时500ms
  }
}

编译、下载、运行。如果LED以1秒的频率闪烁,恭喜你,环境搭建成功了。

小技巧:下载程序时如果提示找不到芯片,检查一下Boot0引脚是否接地。我刚开始学的时候,这个问题卡了我一整天。

2.3 GPIO:控制一切的基础

GPIO,全称General Purpose Input Output,通用输入输出口。说白了,就是芯片的"手脚"——你可以让它输出高电平或低电平,也可以读取外部信号是高还是低。

在STM32中,GPIO有8种工作模式。但咱们做植保机器人,常用的就这几种:

  • 推挽输出(Push-Pull):驱动LED、继电器、电机使能信号
  • 开漏输出(Open-Drain):I2C总线、电平转换
  • 浮空输入(Floating):读取按键、传感器数字信号
  • 上拉/下拉输入:防止引脚悬空,读取稳定的电平

我记得有一次做植保机器人的避障传感器,用的是红外对管。传感器输出信号不稳定,老是误触发。后来发现是GPIO没配置内部上拉,引脚悬空了。加上上拉电阻后,问题解决。

避坑指南:我曾经在项目中直接把5V信号接到3.3V的STM32引脚上,结果烧了一个IO口。STM32的GPIO耐压是3.3V,绝对不能直接接5V!需要用电平转换芯片或者分压电阻。

2.4 定时器:精准控制时间的利器

定时器,是嵌入式系统里最常用的外设之一。没有定时器,你连一个精确的延时都做不了。

STM32的定时器分三类:

  • 基本定时器(TIM6/TIM7):只能计时,没有外部引脚
  • 通用定时器(TIM2-TIM5):有输入捕获、输出比较、PWM等功能
  • 高级定时器(TIM1/TIM8):功能最全,支持互补PWM、刹车输入等

在植保作业中,定时器最常见的用途有两个:

第一,产生PWM波控制电机。比如控制无刷电调或者舵机,就是靠改变PWM的占空比来实现的。

// 配置TIM2输出PWM,频率50Hz,占空比可调
void MX_TIM2_Init(void)
{
  TIM_OC_InitTypeDef sConfigOC = {0};
  
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 72 - 1;      // 72MHz / 72 = 1MHz
  htim2.Init.Period = 20000 - 1;      // 1MHz / 20000 = 50Hz
  HAL_TIM_PWM_Init(&htim2);
  
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 1500;             // 1.5ms 脉宽(舵机中位)
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

第二,做定时中断。比如每10ms采集一次GPS数据,每100ms更新一次路径点。这些周期性任务,用定时器中断最合适。

// 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM3)
  {
    // 每10ms执行一次
    Read_GPS_Data();
    Update_Path_Point();
  }
}

你想想看,如果没有定时器,你只能用HAL_Delay()来延时。但Delay是阻塞的,CPU啥也干不了。用定时器中断,CPU可以一边处理其他任务,一边等定时器"叫醒"它。

核心要点:定时器的精髓在于——不占用CPU资源,精准触发。在植保机器人这种需要同时处理多个任务的场景下,定时器是必不可少的。

2.5 本章小结

这一章我们讲了STM32的基本概念、开发环境的搭建、GPIO的使用、以及定时器的配置。说实话,这些东西看起来零散,但它们是嵌入式开发的"基本功"。就像盖房子,地基打不好,后面再漂亮的算法也跑不起来。

下一章,我们会开始讲传感器数据采集——GPS、IMU、超声波这些植保机器人常用的传感器,怎么跟STM32对接。到时候你会发现,有了GPIO和定时器的基础,一切都顺理成章。

好,今天就到这里。有问题随时交流。


公众号:蓝海资料掘金营,微信deep3321