1. 为什么嵌入式AI编程要选VS Code:Keil和CubeIDE的短板与VS Code的生态优势
先说个我自己的真实感受。在接触AI编程之前,我一直用Keil MDK写STM32的代码,后来项目变复杂了,换到STM32CubeIDE,折腾了大概半年,最后还是把主力编辑器迁移到了VS Code上。原因其实很简单——AI编程工具几乎都优先支持VS Code,这不是巧合,而是生态选择的必然结果。
嵌入式这个圈子有个尴尬现状:写代码的IDE(Keil、IAR)在代码编辑体验上还停留在十年前,补全靠猜,界面老旧,更别说接入AI助手了。CubeIDE虽然基于Eclipse,功能全但启动慢、吃内存,查个函数定义等半天,AI插件支持也稀稀拉拉。而VS Code这边,C/C++扩展、Git集成、终端、远程开发这些基础设施都非常成熟,更重要的是几乎所有AI编程插件——Claude Code、Codex、DeepSeek的IDE插件、通义灵码、Kimi等——都首选支持VS Code,有些甚至只支持VS Code。
先泼一盆冷水:VS Code不是用来替代Keil或CubeIDE的,而是作为代码编写和AI辅助的主力入口。编译、烧录、调试,你可以继续用Keil或者CubeMX生成的工程在命令行或对应IDE里做。VS Code负责最核心的代码编辑、阅读、AI生成、智能跳转、文件管理这部分工作。简单类比就是:VS Code是你的写作工作台,Keil和CubeIDE是印刷厂,你先在写作台上把稿子写好,再送去印刷,而不是直接在印刷机上打字。
咱们这个系列讲的是"嵌入式软件AI编程",核心就是用AI帮你快速生成、修改、理解嵌入式代码。AI编程工具(尤其是Agent类型的)通常需要在编辑器里有完整的文件树、终端、问题面板,还要能读取编译器的错误输出——VS Code恰好把这些都打包了。所以这篇先把地基打好:VS Code装好、STM32相关扩展配好、AI插件接入,后续系列文章里的提示词和skill才能跑得起来。
2. 安装VS Code最容易忽略的几个细节:版本选择、组件勾选和国内下载源
2.1 下载之前先想清楚:装User版还是System版
VS Code官网的下载按钮很大,大多数人直接点了就装。但这里有个对嵌入式开发实际有影响的细节:Windows下有User Installer和System Installer两个版本。
- User Installer:不需要管理员权限,安装在当前用户目录下,配置和环境变量都在用户级,适合电脑权限受限的办公环境。
- System Installer:全机器可用,需要管理员权限,适合你完全掌控自己的开发机。
我做嵌入式开发是自用电脑,选的是System版本,理由是后面要配合命令行工具(比如CMake、Ninja、arm-none-eabi-gcc)时,System版对系统PATH的处理更省心。如果你在公司电脑上装,权限受限,直接选User Installer就行,功能上没有区别。
2.2 安装向导里那个"添加到PATH"必须勾上
安装到选择附加任务那一步,有个复选框叫"添加到PATH",默认是不勾的。这个对嵌入式开发很重要,因为我们要在VS Code的终端里直接使用arm-none-eabi-gcc编译、用OpenOCD烧录,如果VS Code没有加入PATH,后续配置任务和调试器的时候会遇到一堆路径找不到的报错。勾上之后,你在任意终端窗口都能直接敲code命令打开VS Code,非常实用。
安装完成后建议打开一个终端,敲一下code --version验证PATH是否生效。如果提示找不到命令,可以先重启终端再试,还不行就手动把安装目录(默认是C:\Users\你的用户名\AppData\Local\Programs\Microsoft VS Code)加到系统环境变量Path里。这个细节很多教程不提,但等到要用CLI方式打开工程时会卡很久。
2.3 官网直连慢或打不开时,用国内镜像源下载
这是国内开发者绕不开的痛。VS Code官网下载走的是微软自家CDN,有时候速度很慢。我个人的方案是直接用国内镜像源,比如清华TUNA、阿里云的镜像站,都提供VS Code安装包的镜像,版本更新也及时。
镜像站下载有个好处是断点续传稳定,而且下载的安装包和官网一模一样,校验一下哈希值就可以放心安装。不要随便在第三方站点下载所谓"绿色版""破解版",这些版本可能被植入广告或不明组件,搞开发环境最怕这种来路不明的东西。
2.4 安装完先做两件事:界面中文和自动保存
VS Code默认是全英文界面,对很多习惯中文界面的嵌入式工程师来说有点劝退。装完打开扩展面板(Ctrl+Shift+X),搜"Chinese",装微软官方的"Chinese (Simplified) (简体中文) Language Pack",装完重启就是中文界面了。
还有个建议在IDE层面配好:打开设置(Ctrl+,),搜索editor.formatOnSave,勾上保存时自动格式化;搜索files.autoSave,设置成afterDelay,延迟默认1000ms即可。这两个设置对AI生成代码场景特别有用——AI吐出来的代码通常缩进和格式都是对的,但偶尔会混入奇怪的tab和空格,保存时自动格式化能让代码保持整洁,也能让AI后续的理解更准确。
3. STM32扩展配置:让IntelliSense不再满屏红色波浪线
3.1 必装扩展清单:C/C++、Cortex-Debug和Embedded Tools
VS Code装完只算有了一半,真正让它能用来看STM32代码的是一套扩展组合。以下是我实测下来最核心的几个,按重要性排序:
| 扩展名 | 发布者 | 作用 | 必装理由 |
|---|---|---|---|
| C/C++ | Microsoft | 语法高亮、IntelliSense、调试支持 | 没有它看C代码等于用记事本,是所有C/C++开发的基础 |
| Cortex-Debug | marus25 | ARM Cortex-M芯片的调试器 | 配合ST-Link可以像在Keil里一样单步调试、看寄存器 |
| Embedded Tools | Microsoft | 嵌入式开发辅助,包含串口监视、RTOS视图等 | 官方出品,现在嵌入式场景算标配 |
| CMake Tools | Microsoft | CMake工程配置、构建、调试 | 如果工程用CMake管理,这个是必备 |
| Arm Assembly | dan-c-underwood | ARM汇编语法高亮 | 看启动文件startup_stm32xxx.s时需要 |
这里有个配置陷阱我要重点说。很多新手装上C/C++扩展,打开STM32工程之后,发现到处都是红色波浪线,各种#include标红,函数定义跳转不过去。第一反应是"扩展没装好",其实问题出在缺少编译相关的配置信息——VS Code不知道你的HAL库路径、CMSIS头文件路径在哪里。
3.2 用c_cpp_properties.json把HAL库和CMSIS路径告诉VS Code
C/C++扩展通过一个名为c_cpp_properties.json的配置文件来了解你的头文件搜索路径、编译器路径和C标准。这个文件需要放在.vscode目录下。
最简单的做法:命令面板(Ctrl+Shift+P),执行"C/C++: Edit Configurations (JSON)",VS Code会自动生成一个默认配置文件,然后我们往里面加内容。以STM32CubeMX生成的工程为例,假设工程根目录结构是这样的:
MyProject/ ├── Core/ │ ├── Inc/ │ └── Src/ ├── Drivers/ │ ├── CMSIS/ │ └── STM32F4xx_HAL_Driver/ ├── .vscode/ └── Makefile配置内容大致如下:
{ "configurations": [ { "name": "STM32", "includePath": [ "${workspaceFolder}/**", "${workspaceFolder}/Core/Inc", "${workspaceFolder}/Drivers/STM32F4xx_HAL_Driver/Inc", "${workspaceFolder}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", "${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", "${workspaceFolder}/Drivers/CMSIS/Include" ], "defines": [ "USE_HAL_DRIVER", "STM32F407xx" ], "compilerPath": "arm-none-eabi-gcc", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "linux-gcc-x64" } ], "version": 4 }里面的关键点:
includePath是红色的源头,漏一个路径就可能几十个文件报找不到头文件。CubeMX生成的工程,Core/Inc放着main.h、stm32f4xx_hal_conf.h这些关键头文件,Drivers下是HAL库和CMSIS,这两个是主战场,一定不能漏。defines里面的USE_HAL_DRIVER和STM32F407xx必须跟你的芯片型号对应。HAL库源码里很多地方用条件编译控制是否启用某段代码,比如#ifdef USE_HAL_DRIVER,不定义这个宏,头文件内容就会走错分支,甚至是空的。compilerPath如果想让IntelliSense的分析更准确,最好指到你实际交叉编译器的位置,比如C:/STM32CubeCLT/arm-none-eabi/bin/arm-none-eabi-gcc.exe(Windows路径注意用正斜杠)。如果暂时没装独立编译器,写arm-none-eabi-gcc也能工作,前提是PATH里能找到这个命令。
填完保存,红色的波浪线问题基本会消失一大部分。如果还有个别文件标红,鼠标悬停查看错误信息,一般都能看出是缺某个具体头文件,按路径补进includePath就行。
3.3 用CubeMX生成工程时顺手打开"Generate Under Root"简化路径管理
说个我个人经验。STM32CubeMX默认生成的工程结构是工程名/文件夹下包含MDK-ARM、Core、Drivers等子目录,其实这没问题。但如果你用的是CMake或Makefile构建方式,且想让VS Code的${workspaceFolder}直接指向工程根,建议在CubeMX的项目管理器(Project Manager)页面,把"Project Structure"选为"Advanced",然后勾选"Generate Under Root"(有的版本叫"Do not generate the main project folder")。这样生成的工程文件直接在当前文件夹根目录下,路径更扁平,VS Code也不用层层翻目录找头文件。
当然这不是强制要求,只是我实测下来,扁平结构在AI编程场景有额外的好处:AI工具读取代码时,路径越短,上下文越紧凑,AI的理解准确率也越高。
4. 把AI编程助手接进VS Code:插件选型、API接入与嵌入式场景专属提示词
4.1 AI插件分三类:补全型、对话型和Agent型,别混为一谈
VS Code扩展市场里的AI编程工具五花八门,但本质上分三类:
- 补全型:TabNine、GitHub Copilot的补全模式,这类工具在你写代码时实时预测下一段代码。对嵌入式场景,它们能帮你快速写完一些重复性的HAL配置代码(比如GPIO_InitTypeDef的初始化),但对整个模块的架构和逻辑理解有限。
- 对话型:通义灵码、Kimi、CodeGeeX这类,你可以在侧边栏直接和AI对话,让它解释代码、生成函数。这类工具胜在灵活,嵌入式工程师可以把自己遇到的编译错误直接贴给它,或者让它把一段寄存器配置代码讲明白。
- Agent型:Claude Code、Codex、DeepSeek的Agent模式,这类工具能读写你的项目文件、自动运行命令、根据你的指令主动修改多个文件。比如你说"把这个ADC采集逻辑改成DMA模式",Agent型工具会自己去翻头文件、查HAL库函数,然后改代码、甚至帮你编译验证。
对STM32开发来说,我的建议是至少装一个对话型和Agent型搭配用。对话型用来快速问答——遇到HAL_TIM_IC_CaptureCallback的用法不确定,直接问它更快;Agent型用来干重活——让它重构代码、生成整个外设驱动、排查编译错误。
4.2 接入方式:IDE插件直装和API接入各自的适用场景
接入AI插件有两条路:直接装插件登录。比如通义灵码、CodeGeeX这类国内工具,插件装完扫码登录就能用,最省心。另一条路是API接入——你有一个模型服务的API Key(比如DeepSeek、通义千问的API,或者某些兼容OpenAI协议的第三方服务),配上Claude Code这类支持自定义API地址的工具,在设置里填上base_url和API Key就能用。
这两种方式怎么选?我个人经验的判断标准:
- 不想折腾、想开箱即用:走插件直装,通义灵码这类工具对嵌入式代码的HAL库知识库覆盖已经不错了
- 想要更强的代码改写能力、且愿意花时间调参数:走API接入Agent型工具,灵活性和上限更高
- 团队协作:优先用插件直装加统一账号,API Key共享在团队里不好管理,容易泄露
这里提一个很多教程不会细说的坑:用API接入方式时,很多模型在temperature参数上需要有意的设置。代码生成任务跟聊天任务不一样,温度设太高(比如0.7以上),AI会发挥过度,生成一些语法正确但没必要的代码;设太低(0.1),又会显得机械。我建议代码生成相关把temperature设在0.2附近,逻辑解释类的对话可以调到0.4。
4.3 给嵌入式AI模型的专属提示词:强制它先读HAL库文档再加代码
很多工程师用AI写嵌入式代码,第一轮生成的函数看起来像模像样,编译却报一堆错,根本原因是AI对特定芯片型号的HAL库版本、宏定义、结构体字段不够了解。这不完全是AI能力的问题,很大程度上是它的上下文里缺乏你项目里实际使用的HAL库API列表和寄存器定义。
解决方式:写一个固定的系统提示词(System Prompt),让AI在生成代码前先做两件事——分析芯片型号对应的HAL库版本,检查相关外设的初始化结构体字段是否与库文件一致。下面这个提示词模板是我在STM32F4系列上实测效果不错的:
你是嵌入式软件专家,熟悉STM32系列和HAL库。 在生成或修改代码之前,你必须要: 1. 先查看当前工程中 Drivers/STM32F4xx_HAL_Driver 的版本,确认所用的API在这个版本中确实存在 2. 对于外设初始化结构体(如 GPIO_InitTypeDef、ADC_InitTypeDef),列出你计划配置的字段,并逐一与库头文件中的定义核对 3. 只在核对无误后再给出最终代码 如果某个API或字段在你的知识库中不确定,请明确说明,不要猜测。这个提示词的原理,是让AI在生成前先做"充分条件检查",相当于模拟了一个有经验的工程师去查参考手册再动手编码的过程。实际体验下来,加了这段之后,AI生成的HAL代码编译错误率明显降低,尤其是在引脚复用(AF)配置和中断回调函数原型这些容易错的地方。
4.4 让AI先搜代码库再回答:MCP或上下文注入的必要性
你会发现一个规律:让AI在你自己的工程上下文里回答问题,比让它凭空生成代码靠谱得多。VS Code的AI插件大多支持某种上下文引入机制,最新的叫MCP(Model Context Protocol),通俗讲就是允许AI调用工具去检索代码、查文档、运行指定命令。
在嵌入式场景,我更推荐一个简单的做法:在对话时手动把关键文件的路径和结构粘贴给AI。比如你让AI帮忙修改main.c中的时钟配置,先把文件里的SystemClock_Config函数贴出来,再让AI基于这段现有代码做修改。这个习惯对应的是嵌入式工程师都知道的圈——AI不掌握你的项目现场,你主动喂给它上下文,它反馈的代码才贴合实际。
顺带说一个我在这个系列前面文章里详细展开过、这里提醒一下的点:AI编程的"skill"不只是给大模型的提示词,还包含一套工作流程约定。比如我个人的习惯是,在工程目录下放一个CONTEXT.md文件,里面写清楚芯片型号、HAL库版本、外设使用列表、引脚分配表、编译器类型。每次跟AI对话前让AI先读这个文件,效果远好于反复在对话里粘贴同样的背景信息。
5. 用CubeMX生成工程跑通整个工具链:从打开到AI辅助改码的完整验证
5.1 用CubeMX生成一个最小工程,验证VS Code配置是否有效
理论讲了半天,接下来用一个完整的实验验证配置是否真的生效。我以STM32F407VET6为例,生成一个只带UART串口功能的最小工程,演示如何从CubeMX一路走到VS Code,最后用AI插件实际生成一段串口发送代码。
第一步,CubeMX里新建工程,选好芯片型号,配置USART1为异步模式,波特率115200,其他保持默认。在Project Manager里,Toolchain选Makefile(这样工程不依赖Keil或CubeIDE,VS Code可以直接用命令行编译),勾上"Generate Under Root"。
生成工程后,打开VS Code,用"File -> Open Folder"选择工程根目录。此时VS Code可能会提示"是否信任此文件夹中的文件",点信任。打开Core/Src/main.c,如果没有满屏红波浪线,说明前面的c_cpp_properties.json配置基本到位了。
5.2 配置构建任务:让VS Code终端里能一键make编译
CubeMX生成Makefile工程后,我们需要让VS Code能直接调用make命令编译,这样AI帮我们改完代码后,不用切回Keil,直接在VS Code里就能验证编译结果。
VS Code的构建任务可以通过.vscode/tasks.json来定义:
{ "version": "2.0.0", "tasks": [ { "label": "Build STM32", "type": "shell", "command": "make", "args": ["-j4"], "group": { "kind": "build", "isDefault": true }, "problemMatcher": [ "$gcc" ] } ] }这段配置做了什么?它告诉VS Code:按Ctrl+Shift+B时,运行make -j4命令编译工程。problemMatcher里的$gcc意思是把编译输出里符合GCC格式的错误和警告解析出来,在"问题"面板里自动列出,AI改完代码后哪里错了,一眼就能看到,不用去终端里翻日志。
前提是系统里装了arm-none-eabi-gcc和make。如果你装了STM32CubeCLT(STM32的命令行工具集),这两个工具都有了。Windows下还需要一个环境变量的配置:把C:\ST\STM32CubeCLT_1.x.x\GNU-tools-for-STM32\bin路径加到PATH里。验证方式:终端敲arm-none-eabi-gcc --version,能输出版本就说明OK。
5.3 实操:让AI生成串口发送函数并当场编译验证
工具链通了的爽感,在实测AI改码时体现得最明显。我打开main.c,把下面这段需求发给AI助手(这里以对话型插件的侧边栏为例):
项目是STM32F407VET6,HAL库,USART1已通过CubeMX初始化,波特率115200。请生成一个发送字符串的函数,需要处理字符串长度超过缓冲区的情况,并提供调用示例。AI很快返回了一段代码,核心使用的是HAL_UART_Transmit:
void UART_SendString(UART_HandleTypeDef *huart, const char *str) { if (str == NULL) return; uint16_t len = strlen(str); const uint8_t *pData = (const uint8_t *)str; // 如果发送超时,重试一次,实在不行就丢弃本次数据 while (len > 0) { uint16_t chunk = (len > 255) ? 255 : len; if (HAL_UART_Transmit(huart, pData, chunk, 1000) != HAL_OK) { // 发送失败,简单处理:延时后继续尝试 HAL_Delay(1); } pData += chunk; len -= chunk; } }这段代码乍看没问题,但有几个嵌入式老手一眼就能发现的隐患:
HAL_UART_Transmit在阻塞模式下,如果发送缓冲区满或者硬件出错,会返回HAL_BUSY或HAL_ERROR,代码里只简单延时重试,没有区分错误类型,在高负载系统里可能导致数据错乱。- 用
while (len > 0)循环拆包,本质是分块发送,但如果某个chunk发送失败,循环会无限重试,造成阻塞卡死。
我把这两个问题告诉AI,要求它改用中断方式发送,并且加上超时和错误回调处理。这个迭代过程正是"AI编程"的核心用法:不是让AI一把梭生成全部代码,而是把一个任务拆成多轮对话,每轮聚焦一个点,逐步把代码打磨到生产可用的标准。
最终AI改成了基于HAL_UART_Transmit_IT的异步发送框架,并补上了HAL_UART_TxCpltCallback回调函数来处理发送完成后的下一块数据。整个迭代过程里,VS Code的IntelliSense一直在起作用,AI生成的函数被调用时,参数类型有没有写错,返回值用没用对,光标悬停就能看出来。
5.4 编译验证和烧录调试:VS Code、命令行和CubeIDE的分工建议
改完代码,按Ctrl+Shift+B触发构建任务,终端里刷刷刷输出编译日志,最后出现"Build Finished"或者没有Error的提示,说明这一步通过了。
烧录调试的方式,我分享一下个人目前用的分工组合:
- 日常代码编写和AI交互:90%的时间在VS Code,AI插件负责生成、解释、重构代码,C/C++扩展负责智能提示和跳转
- 编译验证频率高的时候:也在VS Code终端里make,编译错误直接看问题面板
- 需要调试器看变量和寄存器时:我习惯用CubeIDE,因为它的调试器界面(基于Eclipse)对硬件外设寄存器的可视化做得比VS Code的Cortex-Debug更直观,尤其在排查复杂的时序问题或DMA传输问题时,CubeIDE的外设视图能直接看到各个寄存器的实时值
这套组合磨合下来,开发效率比之前纯Keil时代高不少。最明显的变化是写一个完整的外设驱动模块(比如ADC多通道采集+DMA传输),以前从查手册到验证通过至少半天,现在AI辅助加VS Code编译验证,一个小时左右能出一个初始版本,剩下的时间都花在边界条件的处理上。
6. 最后再分享一个小技巧:把AI插件配置成"先解释再动手"模式
如果你也是一路配置到这一步,基本环境已经齐了。最后一个建议,跟效率无关,但能省掉不少隐形坑:在AI插件的设置里,找到类似"Auto-apply"或"自动执行"的相关选项,我建议关掉,改成"先解释,再等确认"的模式。
原因很简单,嵌入式代码跟Web前端代码不一样,改动一个外设的初始化顺序、一个中断回调函数,可能影响整个系统的时序。AI是概率模型,它判断"这样改应该没问题",但不会像有经验的工程师那样评估改动对实时性的影响、对临界区保护的影响。所以让AI先给出方案说明,你自己判断后再让它动手改,这个二次确认的环节不能省。
我吃过一次亏:让Agent模式的AI优化一段ADC采样代码,它自作主张把连续转换模式改成了单次转换模式,理由是"减少功耗",结果整个数据采集逻辑全乱了,排查了半天才发现只是模式被改了。从那以后,凡是对已有逻辑动刀子的操作,一律先看方案再放行。
到了这一步,VS Code + STM32扩展 + AI插件的开发环境就齐活了。后面的系列文章讲到的skill、提示词、多文件代码生成,都会基于这套环境来跑。如果安装和配置过程中遇到具体的报错——扩展装不上、头文件找不全、编译任务起不来——欢迎在评论区留言,我尽量抽时间帮你看看。