2. STM32裸机工程结构与构建体系

做嵌入式开发,第一道坎就是搭环境。很多人觉得这事简单,装个软件嘛,下一步下一步就完了。但我在项目里见过太多次因为环境没搭好,浪费一整天甚至一周的情况。所以这一章,咱们把每一步都走扎实。

2.1 工具链全景图

先搞清楚我们要装哪些东西,它们各自干什么活。我习惯画一张图来理清关系:

STM32裸机开发工具链 Keil MDK-ARM 编译器 + 调试器 + IDE STM32CubeMX 图形化配置 + 代码生成器 烧录工具 ST-Link / J-Link / DAP-Link 输出:可烧录的 .hex / .bin 文件 通过烧录工具下载到 STM32 芯片 Flash 💡 我的建议 • Keil MDK 负责编译和调试,CubeMX 负责生成初始化代码 • 两者配合使用:CubeMX 生成工程 → Keil 打开并编写业务逻辑 • 烧录工具用 ST-Link 最省心,买开发板一般都自带

说白了,Keil 是咱们写代码、编译、调试的主战场。CubeMX 是个好帮手,帮你把芯片外设的初始化代码自动生成出来,省得你对着寄存器手册一行行敲。烧录工具就是把编译好的二进制文件塞进芯片 Flash 里。

2.2 Keil MDK 安装与破解

Keil MDK 的安装包可以去 ARM 官网下载,或者找代理商要。我个人习惯用 MDK 5.38 或 5.39 版本,太新的版本有时候对老芯片支持不好,太旧的又缺新功能。

安装步骤

  1. 下载安装包:MDK-ARM 安装文件,大约 1GB 左右。
  2. 运行安装程序:一路 Next,路径建议不要有中文和空格。我一般装到 C:\Keil_v5。
  3. 安装器件包:安装完成后,打开 Keil,点击 Pack Installer,找到你的芯片型号(比如 STM32F103C8),点击 Install。
  4. 注册许可证:这一步比较关键。Keil 是需要 license 的,不注册的话代码限制 32KB。

⚠️ 避坑指南

我曾经遇到过装完 Keil 后死活编译不了,报错说找不到 ARMCC。后来发现是安装路径有空格,而且没装 C/C++ 编译器组件。重装时注意:在安装向导的 Select Components 页面,确保 ARM Compiler 和 C/C++ Compiler 都被勾选。

许可证注册流程

步骤 操作 说明
1 打开 Keil → File → License Management 查看当前许可证状态
2 复制 CID 码 一串 10 位数字字母组合
3 运行注册机(keygen) 选择 Target 为 ARM,粘贴 CID,生成 License
4 将生成的 License 粘贴回 Keil 点击 Add LIC,看到有效期即成功

💡 小技巧

注册机最好以管理员身份运行,否则可能生成失败。另外,有些杀毒软件会误报注册机为病毒,记得加白名单。

2.3 STM32CubeMX 配置与代码生成

CubeMX 是 ST 官方出的图形化配置工具。你想想看,以前配一个定时器要翻几百页参考手册,现在点几下鼠标就搞定了。不过,工具虽好,原理不能丢——我建议刚开始用的时候,每配完一个外设,都去生成的代码里看看对应的寄存器是怎么设的。

安装 CubeMX

  1. 去 ST 官网下载 STM32CubeMX,需要注册账号。
  2. 安装时需要 Java 运行环境,如果没有,安装包会提示你下载。
  3. 安装完成后,打开软件,它会自动检查并更新固件包。

创建一个新工程

咱们以 STM32F103C8T6(蓝色 pill 板)为例,走一遍流程:

  1. 新建工程:File → New Project,在 Part Number 里输入 STM32F103C8,双击选中。
  2. 配置时钟:进入 Clock Configuration 页面,HSE 选择 Crystal/Ceramic Resonator,PLL 倍频到 72MHz。嗯,这里要注意,F103 的最高主频就是 72MHz,别超了。
  3. 配置外设:在 Pinout & Configuration 页面,使能 USART1(用于串口打印),配置 PA9 为 TX,PA10 为 RX。
  4. 配置调试接口:在 SYS 里,Debug 选择 Serial Wire。这一步很多人会忘,导致第一次烧录后芯片就锁死了。
  5. 生成代码:点击 Project Manager,设置工程名和路径,Toolchain / IDE 选择 MDK-ARM,Version 选 V5。然后点击右上角的 GENERATE CODE。

🔑 关键配置清单(F103C8 最小系统)

  • RCC:HSE → Crystal/Ceramic Resonator
  • SYS:Debug → Serial Wire
  • USART1:Mode → Asynchronous,Baud Rate → 115200
  • GPIO:至少保留一个 LED 引脚(比如 PC13)作为输出
  • Clock Configuration:HCLK = 72MHz

2.4 工程模板建立

每次新建项目都从头配一遍 CubeMX?太累了。我习惯建立一个干净的工程模板,以后做新项目直接复制一份。

模板结构

Project_Template/
├── Core/
│   ├── Inc/          // 头文件
│   │   ├── main.h
│   │   ├── gpio.h
│   │   ├── usart.h
│   │   └── ...
│   └── Src/          // 源文件
│       ├── main.c
│       ├── gpio.c
│       ├── usart.c
│       └── ...
├── Drivers/
│   ├── CMSIS/        // ARM 内核抽象层
│   └── STM32F1xx_HAL_Driver/  // HAL 库
├── MDK-ARM/          // Keil 工程文件
│   ├── template.uvprojx
│   └── ...
└── .mxproject        // CubeMX 配置文件

这个结构是 CubeMX 默认生成的,我基本不动它。但我会在 Core/Inc 和 Core/Src 里加一个 app_ 前缀的文件夹,用来放我们自己的业务代码。这样 HAL 库的代码和业务代码就分开了,后期维护起来清爽很多。

在 Keil 中打开工程

生成完代码后,在 MDK-ARM 文件夹下找到 .uvprojx 文件,双击打开。第一次打开可能会提示你安装器件包,按提示操作就行。

打开后,我习惯做几件事:

  • 在 Options for Target 里,把 Output 页的 Create HEX File 勾上。这样编译后会自动生成 .hex 文件,方便烧录。
  • 在 Debug 页,选择调试器为 ST-Link Debugger,然后点 Settings,把 Flash Download 里的 Reset and Run 勾上。这样烧录完程序会自动运行,不用手动复位。

⚠️ 注意

如果勾选了 Reset and Run 但程序没跑起来,检查一下你的 BOOT0 引脚是不是拉低了。BOOT0 接高电平时,芯片会进入系统存储器启动模式,不会执行你的程序。

2.5 烧录验证

环境搭好了,模板建好了,咱们写个最简单的程序验证一下——点灯。这是嵌入式界的 "Hello World"。

编写测试代码

在 main.c 的 while(1) 循环里加上:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();

  while (1)
  {
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    HAL_Delay(500);  // 延时 500ms
  }
}

这里 LED_GPIO_Port 和 LED_Pin 是 CubeMX 根据你的配置自动生成的宏定义。如果你配的是 PC13,那它们就是 GPIOC 和 GPIO_PIN_13。

编译与烧录

  1. 点击 Keil 的 Build 按钮(或者按 F7),编译工程。看底部的编译输出,确保 0 Error(s), 0 Warning(s)。
  2. 用 ST-Link 连接开发板:SWD 接口的 SWDIO、SWCLK、GND,再加一个 3.3V 供电。
  3. 点击 Load 按钮(或者按 F8),开始烧录。烧录完成后,如果一切正常,板子上的 LED 会以 0.5 秒的间隔闪烁。

💡 调试小技巧

如果烧录失败,先检查这几项:

  • ST-Link 驱动是否安装?去 ST 官网下载 ST-Link Utility 或 STM32CubeProgrammer,里面自带驱动。
  • 接线是否正确?SWDIO 接 SWDIO,SWCLK 接 SWCLK,GND 接 GND。别接反了。
  • 芯片是否被锁?如果之前烧录过错误的时钟配置,芯片可能进入硬件错误状态。用 STM32CubeProgrammer 的 Connect under reset 模式擦除 Flash 即可。

2.6 常见问题与解决

问题现象 可能原因 解决办法
编译报错 "cannot open source input file" 头文件路径未添加 在 Keil 的 C/C++ 选项卡里添加 Include Paths
烧录时报 "No ST-Link detected" 驱动未安装或接线错误 重装驱动,检查 SWD 接线
烧录成功但程序不运行 未勾选 Reset and Run,或 BOOT0 拉高 勾选 Reset and Run,检查 BOOT0 引脚电平
LED 不亮 GPIO 配置错误或 LED 引脚不对 核对原理图,确认 LED 连接的 GPIO 和极性