1. 为什么嵌入式开发要转向 VS Code
提到 STM32 开发,很多人脑子里第一反应还是 Keil MDK、IAR 这类老牌 IDE。确实,在很长一段时间里,这两家几乎垄断了 ARM Cortex-M 生态的工具链。但如果你最近接触过开源社区或者逛过嵌入式相关的论坛,会发现一个明显的趋势:越来越多团队把日常编码、代码审查、甚至编译烧录流程整体迁移到了 VS Code 上。
原因其实不复杂。Keil 和 IAR 虽然把编译、下载、调试集成得很顺,但代码编辑器的体验多多少少还停留在十年前的水平——代码补全时灵时不灵,主题少得可怜,跨文件跳转偶尔还会卡壳,更别说拿来写点脚本、看看 Git 提交、顺手接个 AI 辅助编程工具。VS Code 恰恰是在“编辑器体验”这个维度上做到了极致,再加上背靠庞大的插件生态,它的定位早就不是“一款编辑器”这么简单,而是变成了一个几乎什么都能干的平台底座。
这篇文章是这个“嵌入式软件 AI 编程”系列里的第 07 篇,主题就是把 VS Code 装好、把 STM32 相关的工具链拉通。文章面向两类人:一类是刚接触嵌入式、之前只听说过 VS Code 但不知道怎么下手的新手;另一类是长期用 Keil、想换个更现代的开发工作流、但一直没迈出第一步的老手。我会把从下载安装到插件配置、再到工程打开和编译烧录的完整流程讲清楚,顺带讲讲我自己踩过的一些坑。
对于后续所有 STM32 开发工作来说,今天这步是地基。地基打不稳,后面配置编译器、接调试器、跑 AI 辅助编码的时候都会反复出问题。与其到时候东搜一条帖子西问一个人,不如一次性把这些基础配置理清楚。
2. VS Code 本体安装与环境初始化
2.1 官方渠道下载与安装选项
VS Code 的下载渠道只有一个推荐——官网。搜索引擎里搜“vs code 下载”很容易出来一堆第三方站点,界面做得和官网几乎一样,下载按钮却指向捆绑软件或者旧版本,我见过不少同事在这上面中招。官网地址就是一个 code.visualstudio.com 的域名,进入后页面会自动识别操作系统,点击下载 Windows 版即可。
在 Windows 上安装时有几个选项需要留意。第一个是“添加到 PATH”,这个建议勾上,因为后面用命令行调用 code 命令时会很频繁;第二个是“在文件资源管理器上下文菜单中”,勾选后你可以在项目文件夹上右键直接“Open with Code”;还有“将'通过 Code 打开'操作添加到目录文件上下文菜单”,这个同样推荐勾上。点击“下一步”到“选择附加任务”时,别急着一路下一步,把上面这几个关联选项确认好。
安装完成后,打开 VS Code,默认界面是英文的。虽然英文界面不影响阅读,但对于很多习惯中文环境的开发者来说,先把语言切成中文再看插件和配置,心理负担会小很多。切换方式有两种:一种是在左侧扩展栏搜索“Chinese Language Pack for Visual Studio Code”,安装后右下角会提示重启;另一种是通过快捷键 Ctrl+Shift+P 调出命令面板,输入 Configure Display Language,然后选择中文并重启。
2.2 工作区与项目目录规划
VS Code 和 Keil 最大的一个思维差异在于项目结构。Keil 是“打开工程文件”,你需要的是一个 .uvprojx 文件;VS Code 默认是“打开文件夹”,它把你整个项目目录当作工作区。所以我的习惯是给每个嵌入式项目建一个独立目录,比如D:\workspace\stm32\demo_ai,然后用 VS Code 直接打开这个目录。
初学阶段你会发现,VS Code 会在项目根目录下自动生成一个.vscode文件夹,里面存放settings.json、launch.json、tasks.json这类配置文件。这些文件就是 VS Code 的“配置中枢”,后面所有关于编译、调试、烧录的定义都放在这里。
这里有一个很实用的技巧:如果整个团队都在使用 VS Code 做 STM32 开发,把.vscode目录直接提交到 Git 仓库里很有必要。这能让所有成员拿到代码后直接 F5 就能跑起来,不用各自再折腾一遍环境配置。不过要注意,每个人本地的编译器路径可能不同如果没有统一工具链安装路径,可以考虑在settings.json里使用环境变量引用,或者约定所有成员统一装到同一个默认目录。
2.3 侧边栏与常用快捷键热身
装完 VS Code 之后,别急着装插件,先花五分钟熟悉界面。左侧是活动栏,从上到下分别是资源管理器、搜索、源代码管理、运行与调试、扩展市场。对嵌入式开发来说,最常用的就是资源管理器和运行与调试这两个面板。
快捷键方面,有四个我建议你练成肌肉记忆:
Ctrl+Shift+P:打开命令面板。VS Code 的所有操作几乎都能从这里找到入口。Ctrl+P:快速跳转文件。输入文件名就能切过去,比在文件树上点快得多。F5:启动调试。后面配好调试环境之后,按一下开始调试,按 Shift+F5 停止。Ctrl+:打开集成终端。这个终端可以直接调用系统命令,我经常用它来执行编译脚本或是查看 Git 状态。
这些快捷键本身不复杂,但后面每次配置 JSON 文件、写代码、调试的时候都会反复用到,提前熟悉能节省很多不必要的打扰。
3. 必装插件清单与核心功能配置
3.1 插件市场的搜索与安装方式
VS Code 扩展生态是它最大的护城河。在左侧扩展市场里搜索插件时,要注意看三个信息:发布者名称、下载量、最近更新时间。一般官方插件发布者都会有明确的组织名,比如微软发布的插件发布者是 Microsoft,Arm 官方发布的插件发布者是 Arm。下载量和更新时间能帮你筛掉不少无人维护的老旧插件。
安装方式有两种,一种是在扩展市场里搜索后点击 Install,另一种是在项目根目录创建.vscode/extensions.json文件并声明推荐的扩展 ID,这样别人打开项目时 VS Code 会自动建议安装。第二种适用于团队协作场景,可以保证大家的插件版本一致。
3.2 语言和格式化类核心插件
对 STM32 开发而言,下面这几个插件属于“必装”。它们的功能重叠度不高,各管一块,装完之后 VS Code 才真正具备嵌入式 IDE 的雏形。
第一个是 C/C++ 扩展,发布者是 Microsoft。这个插件提供了代码补全、悬停提示、语法高亮、调试支持四大核心能力。没有它,你在 VS Code 里打开一份.c文件就只能看到普通文本,谈不上任何 IDE 体验。
第二个是 C/C++ Extension Pack,它其实是一个合集,里面包含了 C/C++、CMake Tools、C++ TestMate 等几个常用插件。如果你后续会用 CMake 管理工程,这个合集基本可以一步到位。
第三个是 Cortex-Debug,发布者是 DevContainer 社区的维护者。这个插件专门负责 ARM Cortex-M 内核的调试,支持 ST-Link、J-Link、OpenOCD 等主流调试器。它比 C/C++ 插件自带的调试能力更专业,能查看寄存器组、外设寄存器和外设状态,在调裸机程序时几乎是必需品。
第四个是 Chinese Language Pack,这个看个人需求。我建议装上,因为后面配置 JSON 文件时,VS Code 弹出的一些系统提示信息是中文的,对初次接触的人更友好。
3.3 串口监视与 Git 辅助插件
嵌入式开发免不了和串口打交道。传统做法是打开一个独立的串口终端工具,比如 SecureCRT、Xshell 之类的。但 VS Code 里安装 Serial Monitor 插件之后,串口输出可以直接显示在编辑器的面板里,不用来回切换窗口,而且还可以同时开多个串口标签,比独立工具更轻便。这个插件还能设置波特率和行尾格式,对调试日志输出非常方便。
Git 配置方面,VS Code 内置了 Git 支持,但你最好再装一个 GitLens,它能让你在代码的每一行看到最后的提交人、提交时间和提交说明。对团队项目来说,这个信息经常能帮你在排错时理清“这行代码是谁改的、为什么要改”的来龙去脉。
3.4 配置同步与主题选择建议
如果你在多台电脑之间切换开发环境,比如公司台式机加私人笔记本,强烈建议登录 VS Code 账号并开启设置同步。同步内容包括扩展插件、用户设置、快捷键定义等,实测下来同步速度挺快的,而且插件版本会自动匹配。这个功能能省掉不少重复劳动。
主题选择方面,我的建议是开发阶段使用系统自带的高对比度主题,比如 Dark+,它对语法关键词的高亮层次分明,长时间盯着不容易疲劳。至于那些温馨粉嫩的主题,个人喜欢就好,但嵌入式开发很多人要用到 OLED 或者串口抓字,界面稍微朴素一点反而不容易看花眼。
4. STM32 扩展工具链与调试环境搭建
4.1 STM32 VS Code 扩展的官方方案
这里需要重点说一说 ST 官方推出的 STM32 VS Code Extension 集成方案。2023 年之后,ST 官方发布了一整套 VS Code 扩展,包括 STM32 Pack、STM32 VS Code Extension 和 STM32 Embedded Tools 等几个组件。这套插件打通了 STM32CubeMX 生成的代码、Arm 工具链、CMake 构建系统和调试下载之间的断层。
安装方式是在扩展市场里搜索 STM32,就能看到 STMicroelectronics 发布者的相关扩展。安装 STM32 VS Code Extension 时它会自动弹出依赖安装提示,要求你确认安装 STM32CubeCLI 和 ST-LINK 等组件。STM32CubeCLI 是 ST 新推出的命令行工具集合,它把 CubeProgrammer、固件包下载、编译支持都打包进去了,VS Code 扩展会利用它来完成工程生成、固件烧录等动作。
装完这套官方扩展后,你可以在命令面板(Ctrl+Shift+P)里输入 STM32 相关命令,看到诸如STM32: Build、STM32: Download、STM32: Rebuild这些命令,直接点击就能完成构建和烧录,不再需要手动去敲命令或切回 Keil 操作。
4.2 Arm 交叉编译工具链的安装
STM32 编译依赖的并不是本机 PC 的编译器,而是 ARM 官方的交叉编译工具链,通常叫 GNU Arm Embedded Toolchain。这套工具链里包含arm-none-eabi-gcc编译器、链接器、调试器等组件,是整套流程的核心底座。
下载地址在 Arm 官网上有专门页面,选择自己操作系统的安装包。安装时记得勾选“添加环境变量到 PATH”,这步很关键。如果安装时忘了勾选,后续 VS Code 找不到编译器的路径,编译时会报arm-none-eabi-gcc: not found之类的错误。还有一种补救方式是在settings.json里手动指定工具链路径,但不如一开始就把 PATH 配好省心。
安装完成后,在 VS Code 的终端里执行arm-none-eabi-gcc --version,能看到版本输出就说明安装成功。如果提示不是内部或外部命令,那大概率是 PATH 没有生效,重启终端或者重新登录系统后再试。
4.3 ST-LINK 驱动与调试器连接
ST-Link 是 ST 官方调试器,绝大多数使用 STM32 开发板的人手上都有。它的驱动和固件升级工具需要在 ST 官网上下载 ST-LINK 驱动包,安装驱动后电脑才能识别 ST-Link 设备。识别成功与否可以在设备管理器里看到,插上 ST-Link 后“通用串行总线设备”一栏下应该会出现 “STM32 STLink” 相关条目。
接线很容易忽略但非常关键:SWD 接口有四个信号线,分别是 SWDIO、SWCLK、GND、3.3V。开发板上一般都有标注丝印,按顺序接上即可。很多人刚开始调试时报“连接失败”“不能和 target 沟通”,最后发现是杜邦线没插紧或者引脚接错了,这类问题几乎每周都能在网上看到求助帖。
4.4 固件包下载与 CubeMX 代码生成
现在项目里代码生成基本都靠 STM32CubeMX 或它整合进来的 CubeCLI。如果你跟着本系列之前的文章走,应该已经安装过 CubeMX。它的作用是通过图形化界面配置引脚、时钟、外设,然后生成初始化代码。
在 VS Code 工作流里,生成的代码会被保存到一个独立目录,默认情况是在工程的根目录下生成一个 CMakeLists.txt,把你的源文件按文件夹分类。这一步做完之后,整个工程的构建结构就已经确定了,后端再通过 CMake 配合 Ninja 来构建。
所以这里有一个建议:STM32CubeMX 里生成代码时,在“Project Manager”标签页把 Toolchain/IDE 选项选为 CMake,这样生成的工程天生就和 VS Code 的工作流匹配。如果你用的是 Makefile,VS Code 也支持,但配置起来要先配置好构建任务,相比之下 CMake 方案更顺手。
5. 第一个 STM32 工程的编译与烧录细节
5.1 在 VS Code 中导入 CubeMX 生成的工程
连好之后,在 VS Code 中打开项目文件夹。如果项目里已经有 CMakeLists.txt,VS Code 会弹出提示框问你是否配置该项目,点击确认后它会自动识别工具链。
如果没弹出来,也可以在命令面板手动执行 CMake: Select Configure Preset,然后选择 gcc-arm-none-eabi 对应的预设。配置完成后,工程会自动生成 build 目录,这是 CMake 的缓存和产物存放位置,不需要手动去动它。
打开工程后,比较常见的感受是头文件红波浪线。这个现象后面会专门讲原因,这里先提供一个快速生效的办法:直接在 CMakeLists.txt 里定义源文件和头文件路径,然后再执行 CMake: Configure。配置成功后,C/C++ 插件的 IntelliSense 引擎会从 CMake 的 compile_commands.json 中读取编译参数,红波浪线自然就能消失。
5.2 编译命令的选择与输出路径
在 VS Code 里编译有两种方式。官方自带的扩展方法在底部的状态栏工作区会有一个 Build 按钮,直接点击会执行当前预设的构建;或者打开命令面板输入 CMake: Build 也行。我个人更常用的是在集成终端里直接敲命令:
cmake --build build这个命令会自动寻找 build 目录下的 CMake 配置并完成编译。编译完成后,最终的.elf文件、.bin文件和.hex文件都生成在 build 目录下。STM32 官方扩展的烧录命令会优先找.elf文件,因为它里面包含调试符号信息,便于调试器定位源码。
编译时稍微留意一下输出面板是否有 warning 或者 error。STM32 工程里经常遇到的问题是芯片型号宏定义不正确,或者某个外设库函数版本不一致,编译错误信息会直接指向具体代码文件和行号,从这里开始排查效率很高。
5.3 烧录与调试配置实战
烧录这一步,官方 STM32 扩展提供了最省事的路径,只要点击状态栏的“Download”按钮,它就能自动调用 CubeCLI 烧录到 STM32。但如果你更喜欢完全手动控制,也可以直接执行:
STM32_Programmer_CLI --connect port=SWD mode=UR --write build/xxx.bin 0x08000000 --go这条命令是使用 STM32CubeProgrammer 的命令行版,通过 SWD 口连接目标芯片,把编译好的 bin 文件写到地址 0x08000000,也就是 Flash 的起始地址,然后执行。
至于调试,按下 F5 之前需要先配置launch.json。在.vscode/launch.json里新增一个配置,选择调试器类型为cortex-debug,interface 设置为swd,servertype 选择stlink,再加上你编译生成的 elf 文件路径。保存后按 F5 就能连上开发板并停在 main 函数开头,接下来就是打断点、单步执行的老操作了。
{ "version": "0.2.0", "configurations": [ { "name": "STM32 Debug", "type": "cortex-debug", "request": "launch", "servertype": "stlink", "device": "STM32F103C8", "interface": "swd", "executable": "${workspaceFolder}/build/demo_ai.elf", "svdFile": "${workspaceFolder}/STM32F103.svd", "runToEntryPoint": "main" } ] }5.4 编译报错与固件烧录失败的典型处理思路
如果你走到这一步发现有问题,大概率问题会集中在这几个地方:
第一类是最常见的,编译器路径配置错误。报错信息通常是找不到arm-none-eabi-gcc或者某个 CMSIS 头文件。解决办法是检查 CMake 预设中的编译器路径是否和系统环境变量一致。
第二类是烧录时提示无法连接 target。这时候先看 USB 线是否正常、驱动是否装好,然后检查 SWD 的接口接线,最后再看看板子是否需要外部供电。很多人在这一步卡了很久,最后发现板子没上电。
第三类是调试时提示找不到 elf 文件,这多半是编译没有成功,或者启动配置里的可执行文件路径不对。把路径改对,再编译一次就解决了。
提示:如果你遇到“不支持的调试器版本”之类的提示,多半是 ST-Link 固件需要升级,去官网下载 ST-LINK 升级工具跑一遍就能解决。
6. 在线资源与常见报错排查
6.1 理解 VS Code 在这里的定位
首次接触这套工具链的人容易把 VS Code 理解成一个普通的“代码编辑器”,这种认知会导致你遇到问题时不知道怎么定位。实际上,VS Code 在这里的定位更像一个“控制台”,所有编译动作还是由 Arm GCC 在后台执行,VS Code 只是把这些工具整合成可视化操作。
所以如果你哪天遇到编译错误,不要第一时间怀疑 VS Code 坏了,先去看终端里的原始输出。VS Code 只是一个调配工具的入口,编译器和调试器的报错信息才是真正的问题根源。
6.2 头文件红波浪线的完整解决办法
这是新手问得最多的问题,没有之一。尤其是之前用 Keil 的人,把 Keil 工程目录用 VS Code 打开,#include "stm32f1xx_hal.h"下面立刻出现一条红色的波浪线。这并不一定说明头文件真的缺失,而是 VS Code 的 C/C++ 扩展没有正确配置头文件搜索路径。
解决办法分三步。第一步,确认头文件确实存在,去对应的 Include 目录看一眼,多半在Drivers/STM32F1xx_HAL_Driver/Inc;第二步,在.vscode/settings.json里显式添加 includePath;第三步,如果工程是 CMake 管理,先完成一次 CMake: Configure,让 IntelliSense 从构建信息里自动读取路径。
{ "C_Cpp.default.includePath": [ "${workspaceFolder}/**", "${workspaceFolder}/Core/Inc", "${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc" ] }之所以很多人把 includePath 设置了还是不管用,是因为 C/C++ 扩展的 IntelliSense 模式和实际编译模式不一致。CMake 方案下应该把 C_Cpp.default.configurationProvider 设为 ms-vscode.cmake-tools,让 IntelliSense 和编译配置完全对齐。
6.3 工程文件中文路径与特殊字符问题
嵌入式的工程文件路径要避免中文和特殊字符,这一点强调多少次都不为过。比如你把工程放在D:\学习\STM32项目下,Arm GCC 的某些版本在解析路径时可能正常,但调试器和 OpenOCD 等工具的高版本或低版本兼容性表现经常不稳定。最气人的是,有时候编译全程没问题,就差烧录或调试那一步突然报错,查来查去,最后发现是路径问题。
我的建议是:所有嵌入式工程的路径里只使用英文字母、数字、下划线。同理,工程名也不要带空格,CMake 对空格路径的兼容性比 GNU Make 好一些,但你在配置调试任务时会平白多出很多需要转义的地方,不如从一开始就避免这个问题。
6.4 热拔插与多实例运行时的 USB 占用
不知道你有没有遇到过这种现象:VS Code 开着串口监视器,同时又打开 STM32CubeProgrammer 想烧录,结果总是提示连接失败。这是因为串口和调试器共用一个 USB 编号时,某些 ST-Link 设备在串口端口被占用的时候会拒绝调试器连接。
处理办法很简单:先关上串口监视器,烧录完成后再打开。如果你经常需要一边看串口日志一边调试,建议准备一个独立的 USB 转串口模块,日志输出走后者的串口,SWD 调试仍然走 ST-Link,这样两边互不干扰,是实践中效率最高的方案。
7. 实测指南与开发提效心得
7.1 本地验证工具链的完整流程
为了确保环境没有暗坑,建议大家在正式开发前先跑一遍完整的“编译-烧录-运行”链条。我这里给一个简单的自检步骤:
- 新建一个空的 VS Code 窗口,打开一个不包含任何工程代码的测试目录。
- 在终端里执行
arm-none-eabi-gcc --version,确认编译器存在。 - 用 CubeMX 生成一个最小工程,比如只点亮板载 LED,Toolchain 选 CMake。
- 在 VS Code 里打开该工程,执行 CMake: Configure 和 CMake: Build,确认能生成 elf 文件。
- 连接 ST-Link,点击 Download,确认程序烧录后 LED 闪烁。
如果这五步都能通过,说明你的 VS Code 开发环境已经完全就绪,接下来做任何项目都不会卡在环境问题上。
7.2 让 VS Code 舒服一点的细节配置
在settings.json里,有两条配置建议改掉。第一条"editor.formatOnSave": true,每次保存时自动格式化代码,配合.clang-format文件可以统一团队风格;第二条"files.associations"可以让我们把某些无扩展名或自定义扩展名文件识别成 C 语言文件,避免语法高亮失效。
另外推荐安装一个叫 Error Lens 的插件。它可以把编译错误和警告直接显示在出错的代码行后面,不用把鼠标悬停在波浪线上才能看到信息。这对嵌入式这种经常一行报错三行原因的场景非常有用,能省下不少反复悬停的工夫。
7.3 AI 辅助编程的接入方向
这个系列既然叫“嵌入式软件 AI 编程”,最后简单聊两句 AI 怎么接入这套工作流。
VS Code 的 AI 辅助插件生态这两年发展得很快。比较知名的如 GitHub Copilot,做得早、集成度高;Claude Code 等新势力也提供了终端侧的命令行交互工具,可以无缝使用;国内的大模型产品也都在 VS Code 插件市场上提供了各自的接入方案。你完全可以按需选择,通过插件商店搜索安装,然后在插件设置里填入对应模型服务的 API Key 即可。
对嵌入式开发者来说,AI 最主要的使用场景其实是三块。第一块是代码补全,当你写 HAL 库函数时,它能根据上下文自动补全参数列表;第二块是寄存器和库函数配置的问答,比如输入“配置 UART 中断”这样的自然语言请求,它可以直接生成代码片段;第三块是最费我工夫的——帮助分析编译报错信息。很多编译报错信息写得晦涩且长,直接把终端输出丢给 AI,让它定位对应的工程文件和配置问题,能省掉大量阅读理解原始报错的过程。
注意:AI 生成的嵌入式代码建议仔细审查后再烧录。因为它对芯片型号、时钟源配置和引脚冲突缺乏完整的上下文感知,直接硬烧板子容易出问题。用 AI 辅助写框架、写注释、做摘要总结是安全提效的用法。
7.4 我常用的快捷键配置与最终建议
最后分享几个我私藏的 VS Code 快捷键习惯。首先是 Ctrl+Shift+M,快速打开“问题面板”,编译错误和警告全部汇总在这一块,点一下对应条目可以直接跳到源码位置。其次是 Ctrl+Alt+R,这个是 VS Code 自带的快速打开最近项目的快捷键,如果你同时维护多个 STM32 工程,切换项目会非常顺手。还有 Ctrl+B,折叠/展开侧边栏,嵌入式开发经常要盯着代码和终端两头,折叠侧边栏能换来更大的可视区域,用起来很舒服。
根据我个人的实际经验,从 Keil 切到 VS Code 之后的第一个星期多少有点不习惯,毕竟快捷键、构建方式、调试界面都不一样。但只要坚持先把一两个小项目完整走完,你就能感觉到 VS Code 这套方案的优势所在——代码跳转快、插件生态强、终端和串口日志融合、版本管理丝滑,而且一旦你习惯了这套操作,以后再接触其他 MCU 平台,比如 ESP32、RP2040,这套思路几乎可以无缝复制过去,真正的迁移成本比你想象中低得多。
工具只是工具,重要的是给自己省出更多时间去思考代码逻辑本身。VS Code 这个选择,做对了。