2. STM32裸机工程结构与构建体系
做嵌入式开发,第一道坎就是搭环境。很多人觉得这事简单,装个软件嘛,下一步下一步就完了。但我在项目里见过太多次因为环境没搭好,浪费一整天甚至一周的情况。所以这一章,咱们把每一步都走扎实。
2.1 工具链全景图
先搞清楚我们要装哪些东西,它们各自干什么活。我习惯画一张图来理清关系:
说白了,Keil 是咱们写代码、编译、调试的主战场。CubeMX 是个好帮手,帮你把芯片外设的初始化代码自动生成出来,省得你对着寄存器手册一行行敲。烧录工具就是把编译好的二进制文件塞进芯片 Flash 里。
2.2 Keil MDK 安装与破解
Keil MDK 的安装包可以去 ARM 官网下载,或者找代理商要。我个人习惯用 MDK 5.38 或 5.39 版本,太新的版本有时候对老芯片支持不好,太旧的又缺新功能。
安装步骤
- 下载安装包:MDK-ARM 安装文件,大约 1GB 左右。
- 运行安装程序:一路 Next,路径建议不要有中文和空格。我一般装到
C:\Keil_v5。 - 安装器件包:安装完成后,打开 Keil,点击
Pack Installer,找到你的芯片型号(比如 STM32F103C8),点击 Install。 - 注册许可证:这一步比较关键。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
- 去 ST 官网下载
STM32CubeMX,需要注册账号。 - 安装时需要 Java 运行环境,如果没有,安装包会提示你下载。
- 安装完成后,打开软件,它会自动检查并更新固件包。
创建一个新工程
咱们以 STM32F103C8T6(蓝色 pill 板)为例,走一遍流程:
- 新建工程:File → New Project,在 Part Number 里输入 STM32F103C8,双击选中。
- 配置时钟:进入
Clock Configuration页面,HSE 选择 Crystal/Ceramic Resonator,PLL 倍频到 72MHz。嗯,这里要注意,F103 的最高主频就是 72MHz,别超了。 - 配置外设:在
Pinout & Configuration页面,使能 USART1(用于串口打印),配置 PA9 为 TX,PA10 为 RX。 - 配置调试接口:在 SYS 里,Debug 选择 Serial Wire。这一步很多人会忘,导致第一次烧录后芯片就锁死了。
- 生成代码:点击
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。
编译与烧录
- 点击 Keil 的
Build按钮(或者按 F7),编译工程。看底部的编译输出,确保0 Error(s), 0 Warning(s)。 - 用 ST-Link 连接开发板:SWD 接口的 SWDIO、SWCLK、GND,再加一个 3.3V 供电。
- 点击
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 和极性 |