前言
大一上的时候,我曾短暂学习过 STM32,当时用的是 keil5 的开发方式。Keil 的代码补全基本没有、所有内容全靠硬写,或者说硬抄。由于当时面临很多压力,所以我暂时终止了STM32的学习。
这次重新出发,我决定换一套更现代化的工具链:
- STM32CubeMX —— 图形化配置引脚和外设,生成初始化代码
- VS Code + STM32 扩展 —— 现代化的代码编辑器,补全、跳转、Git 集成
- HAL 库 —— 用库函数操作外设,先建立工程能力,以后再深入底层
最终效果:通过 VS Code 管理项目,只用写核心的功能代码,一键编译,一键烧录到开发板,LED 灯点亮并闪烁。
工具链概览
先搞清楚每样东西是干什么的:
| 工具 | 作用 |
|---|---|
| STM32CubeMX | 图形化配置芯片引脚、时钟、外设,生成初始化 C 代码 |
| VS Code | 代码编辑器,用于编写业务逻辑 |
| STM32 VS Code Extension | ST 官方插件,集成编译、烧录、调试功能 |
| GCC Toolchain | 编译器(arm-none-eabi-gcc),把代码编译成机器码 |
| ST-Link | 调试器/烧录器,通过 SWD 接口连接电脑和开发板 |
整个工作流程:
1 | CubeMX 配置引脚 → 生成代码 → VS Code 编写LED灯闪烁的逻辑 → 编译 → 烧录 → 跑起来! |
安装步骤
安装 STM32CubeMX
- 去 ST 官网 下载 STM32CubeMX(需要注册 ST 账号,免费)
- 运行安装程序,一直下一步
- 安装过程中它会自动下载芯片支持包(STM32Cube FW_F1 等),等它下载完就行
安装完成后桌面上会有个 STM32CubeMX 的图标。
安装 VS Code 与 STM32 扩展
- 去 VS Code 官网 下载安装
- 安装完成后,打开 VS Code,点左侧的扩展图标(或按
Ctrl+Shift+X) - 搜索 STM32,找到 STMicroelectronics 官方出的 STM32 VS Code Extension,点击安装
- 安装完成后,VS Code 会自动检测并建议安装一些配套工具,确认即可
这个扩展帮我们集成了编译和烧录的功能,不用自己手动配 CMake 和命令行。
安装 ST-Link 驱动
ST-Link 是连接电脑和开发板的调试器。插上电脑后,如果设备管理器里显示黄色感叹号,说明没装驱动。
解决方法:
- 下载 ST-Link 驱动(
en.stsw-link009.zip) - 解压后,64 位系统运行
dpinst_amd64.exe - 安装完成后,重新插拔 ST-Link
- 打开设备管理器,应该能看到
STMicroelectronics STM32 STLink,没有黄色感叹号
如果不想单独装驱动,安装 STM32CubeProgrammer 也会自动装好 ST-Link 驱动。
创建第一个项目
在 CubeMX 中新建项目
- 打开 STM32CubeMX
- 点击 “New Project”
- 在搜索框输入 STM32F103C8T6(我用的是 Keysking大佬开发的集成开发板),双击选中
- 弹窗问是否初始化外设,点 “No”
配置引脚
在 CubeMX 的 Pinout View视图中,芯片的每个引脚都可以点击配置。
配置 LED 灯引脚(PA7):
在芯片图上找到 PA7,点击它
选择 GPIO_Output

在左侧的 Categories面板下面的System Core里找到 GPIO 设置,点击后中间会跳出Configuration界面,如下图所示

选中PA7引脚,下方跳出具体的设置界面

此处本来GPIO output level是low,也就是低电平,把它改成High,高电平即可

其他保持默认:推挽输出、无上下拉、低速度
配置调试接口
依旧是Categories面板下面的System Core,找到 SYS 设置,点击后中间会跳出SYS Mode and Configuration界面,如下图所示:
- Debug 选择 Serial Wire
- 这样 PA13/SWDIO 和 PA14/SWCLK 会被自动配置,用于 ST-Link 调试
这一步很重要!否则烧录一次后,下次 SWD 就被禁用了,再也烧不进新程序。
选择工具链
切换到 Project Manager 标签页:
| 设置项 | 值 |
|---|---|
| Project Name | stm32code-demo |
| Project Location | 选一个纯英文目录–此处我选的是D盘下的stm32project目录 |
| Toolchain / IDE | CMake(关键!一定要选 CMake,而不是其他的) |
| Default Compiler/Linker | GCC |
点击右上角 **”Generate Code”**,生成代码。弹窗问要不要打开项目,选 **”Open Project”**,它会自动用 VS Code 打开。
在 VS Code 中编写代码
项目打开后,目录结构大致是这样:
1 | stm32code-demo/ |
认识 main.c
CubeMX 生成的 main.c 骨架代码结构如下:
1 | int main(void) |
关键点:**USER CODE BEGIN 和 USER CODE END 之间的代码**,CubeMX 重新生成时不会覆盖。你自己的逻辑都写在这之间。
写点灯代码
让 LED 一直亮: 不需要写任何代码。MX_GPIO_Init() 里已经通过 HAL_GPIO_WritePin() 设好了初始电平,灯自然会亮。
让 LED 闪烁: 在 while(1) 里写翻转逻辑:
1 | /* USER CODE BEGIN WHILE */ |
如果用到了 User Label,也可以写成
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
关于 USER CODE 区块
这是 CubeMX 最贴心的设计之一。每次 CubeMX 重新生成代码时:
- ✅
USER CODE BEGIN/END之间的内容会被保留 - ❌ 外部的代码会被完全覆盖
所以养成习惯:所有自己写的代码,都放在 USER CODE 区块里。
常用的 USER CODE 位置:
| 区块 | 位置 | 用途 |
|---|---|---|
USER CODE BEGIN 2 |
MX_GPIO_Init() 之后 |
初始化设置 |
USER CODE BEGIN WHILE |
while(1) 内部开头 |
主循环逻辑 |
USER CODE BEGIN 3 |
while(1) 内部结尾 |
主循环末尾 |
USER CODE BEGIN 0 |
main.c 顶部函数区 |
自定义函数 |
解读 MX_GPIO_Init —— CubeMX 生成的初始化代码
前面提到,CubeMX 帮我们生成了引脚配置代码。但”能用”和”理解”是两回事,我们来看看 MX_GPIO_Init() 函数里每段代码到底在干什么。
完整代码
1 | static void MX_GPIO_Init(void) |
逐行解析
| 代码 | 作用 |
|---|---|
GPIO_InitTypeDef GPIO_InitStruct = {0}; |
定义一个 GPIO 配置结构体,{0} 把所有成员初始化为 0,避免使用未初始化的值 |
__HAL_RCC_GPIOA_CLK_ENABLE() |
使能 GPIOA 端口的时钟。STM32 的外设默认时钟是关闭的,使用前必须开启时钟,否则寄存器写不进。这条是一个宏,背后操作的是 RCC 寄存器 |
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET) |
在配置之前先把引脚输出设为低电平,保证初始时 LED 是灭的,不会出现瞬间闪一下 |
GPIO_InitStruct.Pin = GPIO_PIN_7 |
指定要配置的引脚是第 7 号引脚(PA7) |
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP |
输出模式:推挽输出(Push-Pull)。这是 GPIO 最常用的输出模式——可以输出高/低电平,驱动能力强 |
GPIO_InitStruct.Pull = GPIO_NOPULL |
上下拉:无。LED 是输出引脚,不需要上下拉电阻 |
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW |
输出速度:低速。LED 翻转速度很慢(几百 ms 一次),低速就够用了。速度越快功耗越高、电磁干扰越大 |
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct) |
将上面配置的结构体写入寄存器,GPIO 才真正按我们的设置工作。GPIOA 参数表示操作 A 组引脚 |
关于 GPIO 模式
GPIO_MODE_OUTPUT_PP 是最常用的输出模式,还有一些其他模式你以后会遇到:
| 模式 | 含义 | 典型用途 |
|---|---|---|
GPIO_MODE_OUTPUT_PP |
推挽输出 | 驱动 LED、普通数字信号输出 |
GPIO_MODE_OUTPUT_OD |
开漏输出 | I2C 通信、电平转换 |
GPIO_MODE_INPUT |
浮空输入 | 读取按键、传感器信号 |
GPIO_MODE_IT_RISING |
上升沿触发中断 | 外部中断 |
GPIO_MODE_IT_FALLING |
下降沿触发中断 | 按键中断 |
GPIO_MODE_AF_PP |
复用推挽输出 | UART、SPI 等外设功能引脚 |
目前只需掌握前两个输出模式,后续文章中会接触到更多。
关键理念:CubeMX 生成 → 解析代码 → 脱离 CubeMX
CubeMX 帮我们生成了这段代码,我们可以直接拿来用,但这不意味着可以跳过理解。建议的学习路径是:
- 先用 CubeMX 生成 —— 快速搭建项目,不纠结寄存器细节
- 再解析生成的代码 —— 搞清楚每行配置在做什么
- 最后能不用 CubeMX 也写出来 —— 真正掌握后,即使工作中没有 CubeMX 也能手写驱动
这也是后续所有博客都会保持的风格——不只是展示 CubeMX 的操作步骤,还会解析生成的代码。
编译
写好了代码,怎么编译成开发板能运行的机器码?
通过 VS Code 编译
在 VS Code 底部状态栏,ST 扩展提供了按钮:
- 先点 齿轮图标 “生成” → 开始编译
- 观察底部终端面板的输出
- 看到类似下面的输出就是编译成功了:
1 | [build] Memory region Used Size Region Size %age Used |
其中 RAM 和 FLASH 显示了固件占用的空间,生成完毕 和 退出代码为 0 代表编译成功。
编译产物在 build/Debug/ 目录下:
stm32code-demo.elf— 可执行文件(包含调试信息)stm32code-demo.bin— 纯二进制文件(用于烧录)
常见编译错误
| 错误 | 原因 | 解决 |
|---|---|---|
undefined reference to XXX_Pin |
引脚宏被删了但代码还在引用 | 去 CubeMX 重新配引脚并生成代码 |
arm-none-eabi-gcc: not found |
工具链没装上 | 重新安装 STM32 VS Code Extension |
CMake Error: toolchain file not found |
工具链路径不对 | 确保 STM32 扩展已正确安装 |
烧录
编译通过后,把程序下载到开发板上。
硬件连接
ST-Link 和开发板通过 SWD 接口连接,只需要 4 根线:
| ST-Link | 开发板 |
|---|---|
| SWDIO | PA13 |
| SWCLK | PA14 |
| GND | GND |
| 3.3V | VCC |
有些 ST-Link 还多一根 NRST(复位)线,也可以接上,但不是必须的。
驱动问题排坑
插上 ST-Link 后,如果 VS Code 检测不到设备,大概率是驱动没装。
排坑步骤:
- 打开设备管理器(Win + X → 设备管理器)
- 看有没有
STM32 STLink出现 - 如果有黄色感叹号 → 运行
dpinst_amd64.exe安装驱动 - 装好驱动后,重新插拔 ST-Link
- 设备管理器里应该显示正常
烧录到开发板
驱动正常后,在 VS Code 中:
- 点击左侧的 运行和调试 图标(🦖 或
Ctrl+Shift+D),打开运行和调试面板 - 确认下方 STM32Cube设备与开发板 列表中能看到
STM32 STLink(
- 点击上方的 运行和调试 按钮,选择
STM32Cube:STM32 Launch STLink GDB Server
- 此时 ST-Link 开始连接开发板,终端会输出连接日志
- 点击 VS Code 上方调试工具栏中的 继续 按钮(▶️ 图标)

- 程序开始运行,LED 灯闪烁 🎉
如何确认烧录成功
烧录完成后,如果代码写的是闪烁逻辑,会看到:
- LED 以 500ms 的间隔一亮一灭 💡
- 这说明:程序成功烧录 → 芯片运行 → GPIO 正常翻转
如果灯不亮:
| 现象 | 可能原因 |
|---|---|
| 完全不亮 | 接线反了?引脚号对不对?初始电平设的是 High 吗? |
| 一直亮不闪 | while(1) 里没写 TogglePin 或 Delay |
| 亮一下就不亮了 | 可能芯片复位了,检查电源 |
总结
与传统 Keil 开发的对比
| 对比项 | Keil 方案 | VS Code + CubeMX 方案 |
|---|---|---|
| 界面 | 老旧,2000 年代风格 | 现代化,美观 |
| 代码编辑 | 无补全 | 智能补全、跳转定义 |
| 配置方式 | 手动写寄存器或配图形界面 | CubeMX 统一图形化配置 |
| 项目迁移 | 难跨平台 | 基于 CMake,跨平台 |
| 费用 | 收费(商业版) | 全部免费 |
| 学习曲线 | 陡峭(要学很多很多很多细节) | 平缓(HAL 封装好了,只关心核心功能) |
工作流总结
1 | 1. 打开 CubeMX → 配引脚 → Generate Code |
后续学习路线
点灯是嵌入式开发的 **”Hello World”**,下一步可以学:
- 外部中断 —— 按键控制 LED
- 定时器/PWM —— 呼吸灯、舵机控制
- UART 串口 —— 和电脑通信,打印调试信息
- ADC —— 读取传感器数值
- I2C/SPI —— 驱动 OLED 屏幕、传感器模块
每条路线跑通后,我都会写博客记录下来,欢迎继续关注 😄