VSCode+Keil Assistant 配置 STM32 补全编译烧录
先把结论放前面如果你现在还在 Keil 里一个字母一个字母地敲 STM32 代码同时又眼馋 VSCode 那套丝滑的代码补全和跳转那你大概率的结局是——装了一堆插件、改了半天的c_cpp_properties.json最后发现连编译按钮都找不到然后灰溜溜地滚回 Keil。我见过太多人卡在这一步包括我自己。这篇东西就干一件事把 Keil Assistant 插件这条路线彻底讲透从装软件的顺序、插件配置的每个字段、到代码补全为什么全是红线、再到那些新手一定会踩的编码和路径坑。这篇是写给新手的但我不打算把关键决策藏起来——每一步为什么这么做我都会说清楚。看完你应该能做到在 VSCode 里正常写 STM32 代码有补全、有跳转、能一键编译、能一键烧录并且清楚这套方案的天花板在哪。1. 为什么我最后还是把 STM32 工程搬进了 VSCode1.1 Keil 的问题不在功能在手感Keil MDK 本身没啥可挑的编译器、调试器、芯片包、寄存器视图一应俱全工程管理也稳。对一个只写 STM32 标准库或者 HAL 库的人来说Keil 其实是够用且省心的。真正让人难受的是它那套编辑器的手感代码补全基本靠猜函数参数提示时有时无结构体成员不敲完整点号经常不出来跳转到定义经常跳到头文件的声明而不是源头没有多光标、没有正则替换预览、没有 Git 集成面板主题和字体方案固定长时间盯着眼睛累。这些东西单看都不致命但一天写八小时累积起来的效率损失很可观。更关键的是现代嵌入式项目越来越依赖 Git 做版本管理、依赖脚本做自动化构建而这些在 Keil 里几乎没法优雅地做。1.2 Keil Assistant 到底是什么定位先把这个插件的定位说透能省掉你后面很多无用功。Keil Assistant 做的事情非常朴素它把 Keil 的编译和烧录命令包装成了 VSCode 里的命令。具体来说它读取你的.uvprojx工程文件拿到工程里的文件列表和目标名称然后在 VSCode 侧边栏生成一个树形结构让你能点开看文件。当你点编译的时候它在后台调用UV4.exe -b 工程路径 -o 输出日志相当于帮你敲了一遍 Keil 的命令行。编译日志解析出来错误和警告显示在 VSCode 的问题面板里点一下就能跳到出错的行。所以它的本质是VSCode 负责编辑体验Keil 负责编译和烧录。它不接管编译器不接管调试器也不修改你的工程文件结构。这个定位决定了它的优点改动小老工程直接能用和缺点调试还得回 Keil。1.3 三条路线的取舍你得先想明白配置 STM32 开发环境市面上主流的有三条路我做个对照你先选路线再动手路线编译工具链调试方案上手难度适合谁Keil AssistantKeil ARMCC/ARMCLANG回 Keil 调试低老工程迁移、新手、课程作业Makefile arm-none-eabi-gccGCCVSCode Cortex-Debug中高想彻底脱离 Keil、玩开源工具链STM32CubeCLT CMakeGCC/CLANGVSCode Cortex-Debug中新项目、CubeMX 生成工程这条分岔路口很容易走错。如果你的工程是从老师、同事那里拿来的 Keil 工程里面有.uvprojx那 Keil Assistant 是最省事的半小时能跑起来。如果你想从零建项目并且要完整调试那 CMake Cortex-Debug 更顺。最怕的是你以为 Keil Assistant 能调试——它不能作者也明确说了不做这块。所以我选 Keil Assistant 的理由很简单我的项目是现成的 Keil 工程有几百个文件、多个目标配置重写成 CMake 的成本远大于收益。如果你的情况一样往下看。2. 装之前先想清楚这套环境的依赖链条2.1 软件清单与安装顺序这一步看着简单但顺序错了会浪费你一小时。顺序是有讲究的先装 Keil MDK把芯片包Device Family Pack装好确保能在 Keil 里正常编译出一个点灯工程。Keil 是整个方案的地基地基没打牢VSCode 那边再折腾都是白费。验证 Keil 命令行可用。打开 CMD敲C:\Keil_v5\UV4\UV4.exe -h如果弹出一堆参数说明说明命令行入口是通的。这一步很关键因为 Keil Assistant 走的就是命令行。再装 VSCode。从官网下最新稳定版Windows 上建议选添加到 PATH那个勾。最后装插件。插件依赖前面两个都就位顺序反了它读不到路径。2.2 Keil 版本和授权别在这上面卡住Keil MDK 有两个版本要注意MDK-Lite 是免费的但限制编译后代码大小不超过 32KB准确的说是镜像大小限制稍微复杂一点的工程加上 HAL 库直接超。MDK-Essential/Professional 是商业版需要授权。对新手来说如果你的工程小于 32KBLite 够用。如果超了Keil 会明确报错告诉你超了多少不会静默失败这点还算友好。我建议你先用 Lite 跑通流程确认这套工作流真的适合你再考虑授权的事。另一个坑是Arm Compiler 版本。老工程用的是 AC5armcc新工程可能是 AC6armclang。这两个编译器的语法接受度不一样AC6 对代码规范更严格很多老代码在 AC6 下会报一堆警告甚至错误。你装 Keil 的时候若只勾了一个版本的编译器打开别人的工程可能会报compiler not found。检查方式Keil 里Project → Manage → Project Items → Folders/Extensions看编译器路径是否有效。2.3 VSCode 端最少要装哪几个插件不要贪多装得多冲突也多。核心就这几个Keil Assistant主角负责编译烧录。C/C微软官方负责代码补全、跳转、错误提示。这是体验提升的主要来源没它 Keil Assistant 就只是个编译按钮。Chinese (Simplified) Language Pack想要中文界面的话装这个不想要可以跳过。可选GitLens、EditorConfig、Trailing Spaces工程规范类的锦上添花。这里提醒一句网上有些老教程推荐装C/C Advanced Lint、Browse.vc.db相关的插件别装。微软的 C/C 插件自己那一套 IntelliSense 引擎就够用了再叠一套会出现同一个变量两个插件给出不同颜色提示的诡异现象排查起来很烦。3. Keil Assistant 的配置过程从插件市场到第一个可编译工程3.1 两个关键设置项Keil 路径和 UV4.exe装完插件第一件事是打开设置搜索KeilAssistant。你会看到几个关键项KeilAssistant.MDK.Uv4Path默认值是C:\Keil_v5\UV4\UV4.exe。KeilAssistant.C51.Uv4Path如果你只玩 STM32这条忽略。你的 Keil 如果不是装在默认路径比如装在 D 盘这里必须改。判断方法很简单打开文件资源管理器找到UV4.exe右键复制完整路径粘进去。路径里的反斜杠在 JSON 设置里要写成双反斜杠\\或者干脆用正斜杠/也认。注意改完设置建议重启一次 VSCode。插件的路径读取有些版本是在激活时做的不重启可能读的是旧值会让你怀疑自己是不是改错了地方。3.2 导入工程.uvprojx 和 .uvproj 的区别Keil 的工程文件有两个后缀老的.uvprojKeil 4 时代的格式和新的.uvprojxXML 格式Keil 5。Keil Assistant 两个都支持但.uvproj是老二进制格式解析偶尔会出问题尤其是工程里有中文文件名或者特殊字符的时候。导入流程是用 VSCode 打开工程所在的文件夹然后在 Keil Assistant 面板点那个加号图标选择.uvprojx文件。这时候你会看到面板里出现一个树展开就是工程组和文件。这一步最容易出的问题是面板里空空如也或者只显示了部分文件。常见原因有工程使用了 Keil 的Groups分组而插件只识别某些层级工程路径里有中文或者空格这一点后面单独讲工程引用了绝对路径的外部文件插件解析不到。遇到这种情况先在 Keil 里打开这个工程确认能正常编译再回来看插件。先排除 Keil 自身的问题再排查插件这个顺序能省你很多时间。3.3 一键编译、烧录与快捷键绑定插件跑通之后你能用的命令有Keil Assistant: Build增量编译。Keil Assistant: Rebuild全量重编译。Keil Assistant: Download下载到芯片需要 Keil 里已经配置好下载器。Keil Assistant: Open in Keil直接用 Keil 打开当前工程。这几个命令默认没有快捷键得自己绑。打开keybindings.json加几行[ { key: ctrlaltb, command: keil-assistant.build, when: editorTextFocus }, { key: ctrlaltr, command: keil-assistant.rebuild }, { key: ctrlaltd, command: keil-assistant.download } ]注意命令 ID 会随插件版本变化如果绑了没反应去命令面板CtrlShiftP里搜 Keil看实际命令名是什么再照着改。编译输出面板里会显示 Keil 的原始日志包括Program Size: Codexxxx RO-dataxxxx RW-dataxxxx ZI-dataxxxx这一行。这一行很重要它告诉你代码占了多少 Flash 和 RAM。我习惯把这段截图存档改完功能对比一下能第一时间发现咦怎么突然多了 8KB及时揪出误引入的大数组或者误开的调试打印。4. 让代码补全真正好用c_cpp_properties.json 的坑4.1 为什么默认补全全是红线导入工程之后你十有八九会看到满屏的红波浪线#include stm32f1xx_hal.h那里标着cannot open source file。这不是你的代码错了是C/C 插件不知道头文件在哪。要理解这一点得先分清两件事Keil 的编译和 VSCode 的 IntelliSense 是两套完全独立的系统。Keil 编译时靠.uvprojx里配置的 Include Paths 找头文件VSCode 的补全靠c_cpp_properties.json里的includePath找头文件。两者互不通信。插件作者也没做自动同步技术上可以做但同步逻辑复杂容易出错所以没做。所以你要做的就是把 Keil 里的 Include Paths 手动搬到c_cpp_properties.json。4.2 includePath 和 defines 到底怎么写在工程根目录建一个.vscode文件夹里面放c_cpp_properties.json。以 STM32F103 HAL 库为例{ configurations: [ { name: STM32F103, includePath: [ ${workspaceFolder}/**, ${workspaceFolder}/Core/Inc, ${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc, ${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc/Legacy, ${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32F1xx/Include, ${workspaceFolder}/Drivers/CMSIS/Include ], defines: [ USE_HAL_DRIVER, STM32F103xB ], cStandard: c11, cppStandard: c17, intelliSenseMode: gcc-arm, compilerPath: } ], version: 4 }几个要点解释一下${workspaceFolder}/**表示递归搜索工作区下所有目录。这一条很省事但工程文件特别多的时候会让 IntelliSense 变慢如果卡顿可以去掉它改成精确路径。defines里的STM32F103xB这类宏必须写对。它是 CMSIS 用来选芯片寄存器的写错了会导致补全出来的寄存器地址都是错的或者头文件里的条件编译走进错误分支表现为明明有这个函数但补全不提示。intelliSenseMode选gcc-arm是因为做嵌入式补全时这个模式的解析行为最接近实际。别选msvc-x64那套是针对 Windows 桌面开发的。4.3 defines 从哪抄别靠猜defines最靠谱的来源是 Keil 的工程配置。打开 KeilOptions for Target → C/C → Define那一栏里用逗号分隔的宏原样抄到defines数组里每个宏一个字符串。同理Include Paths那一栏里的每个路径也抄到includePath。这个过程很枯燥但一次性做好后面基本不用动。我通常会在抄完之后故意把鼠标悬停在一个 HAL 函数上看能不能弹出完整的参数说明——能弹出来说明头文件路径对了弹出来是undefined或者什么也没有说明路径还差一条。4.4 几类补全不出来的典型情况补全不生效无非这几种头文件确实没加进 includePath。症状是#include那行有波浪线。加路径即可。芯片包路径没加。CMSIS 的core_cm3.h在芯片包里不在工程目录里需要用绝对路径加进来比如C:/Keil_v5/ARM/PACK/Keil/STM32F1xx_DFP/2.4.1/Drivers/CMSIS/Include。版本号会随更新变化加的时候去文件夹里确认一下。宏定义漏了或写错了。症状是头文件能打开但里面的条件编译块全灰着函数不提示。IntelliSense 引擎卡死了。按CtrlShiftP执行C/C: Reset IntelliSense Database通常能解决。提示修改c_cpp_properties.json保存后IntelliSense 会重新索引大工程可能要等半分钟到一分钟。别急着下结论等右下角的进度条转完再说。5. 那些第一次配置几乎必然踩到的坑5.1 中文路径和空格这是 STM32 开发里最古老、最经典、也最容易被忽视的坑。Keil 命令行对路径中的中文和空格处理得很糟糕表现为命令行调用直接失败或者编译到一半报找不到文件。所以工程路径不要有中文。D:\我的项目\STM32\这种结构迟早出事改成D:\Work\STM32\。工程路径不要有空格。D:\My Project\也不行。用户名是中文的那C:\Users\张三\下的工程也有风险建议把工程放到 D 盘或 E 盘根目录附近。我见过一个同学的工程编译一直失败折腾了一下午最后发现是文件夹名里有个中文的、。换掉立马好了。这种坑不值得你花时间一开始就避开。5.2 GBK 编码的注释乱码Keil 的编辑器默认用 ANSI中文系统下就是 GBK保存文件而 VSCode 默认按 UTF-8 读。结果就是你写的中文注释在 VSCode 里全变成了乱码方框。解决方式有两条我推荐第一条方案一让 VSCode 按 GBK 读。在工作区的.vscode/settings.json里加{ files.encoding: gb2312, files.autoGuessEncoding: true }autoGuessEncoding打开后 VSCode 会尝试自动判断编码大部分情况能猜对。这个方案的优点是不动工程里的文件Keil 那边依然正常风险为零。方案二把工程整体转成 UTF-8。这需要在 Keil 里也做配置加编译选项处理字符集而且如果是 AC5 编译器对 UTF-8 的支持并不好容易出现编译警告。老工程不建议动。这两种方案的取舍很清楚只要 Keil 还在参与编译就别轻易改文件编码。等哪天你彻底切到 GCC 工具链了再统一转 UTF-8 也不迟。5.3 芯片包缺失导致的 Device not found现象是在 Keil 里打开工程弹窗报找不到目标器件或者编译时报一堆Unknown device的错误。原因是你没装对应的 Device Family PackDFP。解决办法是打开 Keil 的 Pack Installer搜索你的芯片系列比如STM32F1找到对应的 DFP 装上。装的时候注意版本有些老工程依赖特定版本装最新版反而会报错。Sei 一般建议先装最新版出问题了再回退。装完之后记得回头把c_cpp_properties.json里芯片包的路径也更新成你实际装的版本号否则补全还是不对。5.4 编译输出乱码和终端编码Keil 命令行输出的日志是 GBK 编码的VSCode 的输出面板默认按 UTF-8 解析于是你看到的编译错误信息里一片乱码——中文全花了英文正常。这倒不影响编译本身但看错误信息很痛苦。处理办法在编译输出里把中文部分忽略掉看英文的报错行号和错误类型就够了。或者更彻底的办法是给 Keil 的编译加英文输出选项。我个人的做法是直接在.vscode/settings.json里设置终端编码{ terminal.integrated.defaultProfile.windows: PowerShell, terminal.integrated.env.windows: { PYTHONIOENCODING: utf-8 } }说实话这一条对 Keil Assistant 的输出面板不一定生效因为那是插件自己的输出通道不是集成终端。所以更实用的建议是关注错误代码和行号别跟中文较劲。5.5 工程引用了工程目录外的文件Keil 允许在工程里添加任意路径的文件。如果这些文件在工程目录之外VSCode 打开工作区时看不到它们方案里的${workspaceFolder}/**也搜不到于是补全失效、跳转失效。我的建议是把工程整理成自包含的结构所有源文件都在工程目录里。实在不行的就把那些外部路径一条条加进includePath和工作区的folders配置里。这是个体力活但是一次性投入。6. 调试怎么办Keil Assistant 管不了这一段6.1 现实做法写代码在 VSCode调试回 Keil先把预期管理好Keil Assistant 不提供调试功能它没有实现和 GDB/ULINK 的对接。所以你的日常是这样一个循环在 VSCode 里写代码享受补全和跳转快捷键编译看问题面板里的错误需要单步、看寄存器、看变量的时候切到 Keil调完发现问题在某个文件切回 VSCode 改。这个循环听起来笨但实际上手之后你会发现——写代码的时间远大于调试的时间把 80% 的时间花在体验好的编辑器上是划算的。而且 Keil 里已经打开的工程你切回去直接按烧录就行不需要重新打开。插件面板里有个Open in Keil命令点一下就跳过去还算方便。6.2 进阶做法Cortex-Debug 加 OpenOCD如果你确实想连调试也一起搬到 VSCode那就得走另一条路跟你用什么编辑器没关系取决于你的编译产物能不能生成 ELF 和调试符号。Keil 编译出来的.axf文件其实就是 ELF 格式理论上是能被 GDB 读的。配置大概是装Cortex-Debug插件装 OpenOCD 或者 J-Link 的命令行工具取决于你手上的下载器写launch.json指定executable为 Keil 输出的.axf文件servertype选openocd或者jlink按 F5 启动调试。这条路能走通但对新手来说门槛不低尤其是 OpenOCD 的配置文件选错会导致连不上目标芯片。我的建议是先用混合方案跑一两个月等你对工具链足够熟了再尝试全 VSCode 调试。别一上来就两条腿一起迈容易摔。7. 团队协作和长期维护的几点经验7.1 哪些文件该进 Git哪些必须忽略用 VSCode 管工程之后很自然会想上 Git。这时候.gitignore要写对不然仓库里全是编译中间产物几十兆的东西传上去会被同事骂。针对 Keil 工程我一般这么写# Keil 编译产物 *.o *.d *.crf *.axf *.htm *.lnp *.plg *.dep *.build_log.htm *.map *.lst # Keil 用户界面状态换机器会重新生成 *.uvguix.* *.uvoptx *.uvopt # VSCode 个人配置 .vscode/ipch/ .vscode/browse.vc.db* # 系统文件 Thumbs.db .DS_Store这里有争议的是*.uvoptx。它保存了断点位置、窗口布局这些用户状态一般不入库。但有些团队的工程师习惯把下载器配置也放在这里面删了之后每个人都要重新配一遍。视团队情况决定但要在 README 里写清楚别让人猜。7.2 换电脑之后的复现清单这套环境是本地配置换台机器就得重来一遍。我给自己整理了一份清单照着做大概 20 分钟能恢复步骤操作检查点1装 Keil MDK 对应 DFP能编译一个点灯工程2验证UV4.exe -h命令行可调用有参数输出3装 VSCode Keil Assistant C/C插件面板出现 Keil 图标4配置Uv4Path为本机实际路径面板能导入工程5clone 代码仓库.uvprojx存在6让同事把c_cpp_properties.json也提交或者自己按 4.2 节重建7绑定编译烧录快捷键快捷键生效第 6 步是我踩过的坑一开始我把c_cpp_properties.json放进了.gitignore结果团队里每个人都要自己配一遍 includePath浪费了大量时间。后来改成把它提交进仓库路径全用${workspaceFolder}相对路径只有芯片包那条绝对路径需要各自改。凡是能用相对路径的地方都用相对路径这是让配置可共享的关键。8. FreeRTOS 和复杂工程的几点补充8.1 FreeRTOS 工程的文件组织移植过 FreeRTOS 的人知道工程里会多出一堆port.c、heap_4.c、FreeRTOSConfig.h。Keil Assistant 对这类工程的导入一般没问题但补全方面要注意FreeRTOSConfig.h通常放在Core/Inc或者专门的Inc目录确认它被includePath覆盖portmacro.h在portable/RVDS/ARM_CM3这类目录下这个目录名跟编译器有关Keil 用的是 RVDS 版本GCC 用 GCC 版本。你把工程给别人的时候要说明这一点不然对方用 GCC 编译会找不到符号中断优先级相关的configPRIO_BITS在FreeRTOSConfig.h里定义如果和 CMSIS 那边的定义冲突会有编译警告。这些不是 Keil Assistant 的问题是工程本身的组织问题但配置补全的时候会放大它。我在配一个 F103C8T6 的 FreeRTOS 工程时就遇到过xTaskCreate补全不出来原因是FreeRTOS.h的 includePath 没覆盖到加上就好了。8.2 多目标工程的索引问题Keil 工程可以配置多个 Target比如一个 Debug 目标、一个 Release 目标宏定义不同。Keil Assistant 一般显示第一个可用的目标。如果你的补全提示跟实际编译的宏不一致检查一下当前选的是哪个目标。这种情况下我通常会在c_cpp_properties.json里配两组 configurations用configurationProvider或者干脆手动切换。VSCode 右下角状态栏可以快速切当前配置改起来不麻烦。9. 一些散碎但很实用的小技巧写到这顺手记几个我日常用得上的第一把 Keil 的输出日志留着。插件输出的日志里包含完整的编译命令行能看到每个文件用了哪些宏和 include 路径。补全出问题时对着这个日志逐条比对c_cpp_properties.json比瞎猜快得多。第二善用CtrlP。大工程里找文件用文件名快速跳转比在文件树里翻快十倍。Keil Assistant 的树形面板更多是用来确认工程结构不是用来找文件的。第三给常用头文件建代码片段。比如main函数的框架、GPIO 初始化模板、串口重定向的代码做成 snippetCtrlSpace一敲就出来。新手觉得这是小聪明等你写过几十个工程就知道这有多省事。第四VSCode 设置里打开editor.formatOnSave: true要谨慎。嵌入式代码里经常有对齐好的宏定义、寄存器位域定义格式化器一跑全给你打乱反而不好读。我一般是关掉的只在需要的时候手动格式化一段。第五别在 VSCode 里改工程文件结构。增删源文件、改文件分组这些还是在 Keil 里做。工程文件是 XML 格式手动改容易改坏改坏了 Keil 打不开插件更读不到。让 Keil 管工程结构VSCode 只管写代码这个边界划清楚能省掉很多麻烦。最后说说我个人对这套方案的判断。它不完美调试那一段始终是个缺口多目标工程也偶尔别扭。但对手里有一个现成的 Keil 工程、想改善写代码体验的人来说它是投入产出比最高的一条路——半天配置换来之后每一天的舒服。至于要不要继续往前走、切到 CMake 加 Cortex-Debug 那套我建议你先用这套写两个完整的项目摸清楚自己到底需要什么再决定。工具是拿来干活的折腾工具本身不该成为目的。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →