前言:
Keil uVision是一个历史非常悠久的嵌入式开发软件。很多STM32学习课程和开发板资料都会默认使用Keil作为主力开发环境,比如野火、江科大以及很多开发板厂家配套的例程。它的优点很明显:工程体系成熟,编译器稳定,下载和Debug体验完整,尤其是J-Link/ST-Link、断点、单步、寄存器、内存窗口这些功能,对单片机开发来说非常直接。
但Keil作为现代代码编辑器就有些吃力了。现在VSCode、Cursor、Trae、CodeBuddy这类编辑器已经很常见,写代码不只是编辑文本,还包括全局搜索、批量修改、Git/GitHub管理、diff查看、AI Coding辅助、文档生成和代码解释。Keil接入AI比较不方便,Git体验也不如VSCode自然,所以我开始考虑把代码编辑迁移到VSCode里。
我一开始也想过直接把旧的Keil工程转成CMake,甚至切到GCC工具链。但实际尝试后发现,这不是我当前最需要的方案。一方面,我已经习惯Keil里的Debug和下载方式;另一方面,如果团队里还有人继续用Keil,那么CMake就会变成第二套工程系统。Keil里加了一个.c文件,CMake也要加;Keil里改了include路径、宏定义、优化等级,CMake也要同步;此外有些国产芯片还不支持GCC编译器。两套工程配置长期并存,很容易出问题。
所以我最后确定的目标不是“抛弃Keil”,而是“让VSCode接管编辑体验,Keil继续负责真实编译、下载和Debug”。本质上IDE只是写代码和调工具的软件,只要底层编译器、源文件、宏定义、链接脚本和下载配置保持一致,用VSCode写和用Keil写,最终编出来的固件应该是一致的。
正文:
1、最终采用的方案
最后跑通的方案是:VSCode + cl.keil-assistant + Keil uVision工程 + ms-vscode.cpptools。其中Keil工程仍然是唯一权威来源,.uvprojx和.uvoptx继续负责源文件列表、include路径、宏定义、编译器版本、芯片配置、Flash算法、J-Link/ST-Link配置和下载后运行。VSCode负责写代码、搜索、Git/GitHub、AI Coding、触发Build和Download。
这里要分清两个插件的职责。cl.keil-assistant负责识别Keil工程并调用UV4.exe编译、下载;ms-vscode.cpptools负责VSCode里的红线、补全、跳转和条件编译识别。也就是说,Keil Assistant能编译通过,不代表VSCode红线一定正常;VSCode红线正常,也不代表新增.c文件已经自动加入Keil工程。
如下图,我建议单独建一个VSCode Profile,比如叫Keil AC5,只在这个Profile里安装Keil相关插件和设置编码。这样不会污染原来的VSCode环境。这个Profile里需要让Keil Assistant指向本机Keil,例如C:\Keil_v5\UV4\UV4.exe。如果工程里有GBK中文注释,也建议打开自动识别编码或设置GBK,否则容易乱码。
![image.jpg]()
2、工作区怎么打开
直接打开最外层目录虽然能一次看到所有例程,但并不是最适合C/C++索引的方式。因为一个大目录下可能有十几个独立Keil工程,VSCode的C/C++插件不知道当前main.c到底属于哪个.uvprojx,很容易退回默认Win32配置,结果就出现stdio.h找不到、uint32_t未定义、__IO未定义、寄存器宏未定义等红线。
比较稳的方式是每个例程一个.code-workspace,工作区包含两个根目录:一个是MDK-ARM,给Keil Assistant识别.uvprojx;另一个是例程源码根目录,方便浏览Src、Inc、Drivers和Readme。这样编译插件能找到Keil工程,人写代码时也能正常看到完整源码目录。
如下图即vscode打开的keil工程,实际体验与keil无太大差异。
![image.jpg]()
编译器版本和J-Link配置
我的这批工程原来指定的是AC5 V5.06 update 6 (build 750),但本机Keil实际安装的是V5.06 update 2 (build 183)。因为当前例程没有依赖build 750的特殊能力,所以我把.uvprojx里的编译器选择统一改成本机已有版本:5060183::V5.06 update 2 (build 183)::ARMCC,同时保持uAC6=0,也就是仍然使用AC5,不切AC6,也不切GCC。
下载器方面,原始工程是ST-LINK,而我使用J-Link。如果多个工程都手动进Keil改一遍会非常麻烦,所以实际做法是先选一个工程在Keil里手动配置好AC5、J-Link和下载后运行,再把这部分配置让Codex同步到其他工程。J-Link相关配置主要在.uvoptx里,例如pMon=Segger\JL2CM3.dll、nTsel=3,并且TargetDriverDllRegistry里要有JL2CM3配置项。下载后运行相关字段包括RunTarget=1、tLdApp=1、tGomain=1。
这一步同步的只是工具链和下载器配置,不是把某个例程的源文件列表复制给其他例程。每个例程自己的源码、文件列表和业务配置仍然保留。最后验证时,Keil实际使用的是本机AC5 build 183,并且基准工程能编译通过,用户侧也确认了Build和Download都可用。
VSCode红线问题
Keil编译已经0 Error(s), 0 Warning(s),但VSCode里仍然满屏红线。典型错误包括stdio.h找不到、uint32_t未定义、__IO未定义、RCC_CR_HSEON未定义。这个时候不要急着改源码,因为这通常不是代码错,而是VSCode的C/C++插件没拿到正确的include路径和宏定义。
Keil编译看的是.uvprojx/.uvoptx,而VSCode红线看的是.vscode/c_cpp_properties.json。Keil Assistant有时会在MDK-ARM\.vscode下生成这个文件,但如果当前打开和编辑的是例程源码根目录,C/C++插件不一定会读取子目录里的.vscode配置。所以最后的做法是:每个例程根目录都放一份.vscode\c_cpp_properties.json,让当前Src\main.c能匹配到正确配置。
这个文件里最关键的是includePath和defines。includePath至少要包含工程自己的Inc、Inc\bsp、HAL头文件、CMSIS设备头文件、CMSIS核心头文件,以及AC5标准库路径C:\Keil_v5\ARM\ARMCC\include和C:\Keil_v5\ARM\ARMCC\include\rw。缺AC5标准库路径会导致stdio.h/stdint.h报红;缺CMSIS路径会导致__IO、寄存器宏、IRQn等报红。
defines里分两类。第一类是真正影响条件编译的工程宏,比如USE_HAL_DRIVER、STM32F407xx、__CC_ARM,这些必须有,否则HAL/CMSIS会走错分支。第二类是为了让VSCode理解AC5扩展语法的兼容宏,比如__asm(x)=、__weak=、__packed=、__inline=、__forceinline=、__nop()=、__enable_irq()=、__disable_irq()=等。这些宏不是给Keil编译用的,只是让VSCode的IntelliSense别把ARMCC5关键字和内建函数当成错误。
这类兼容宏不一定覆盖ARMCC5官方全部内建函数,但对当前STM32F4 HAL/CMSIS例程基本够用。如果以后引入CMSIS DSP、更多内联汇编或特殊intrinsic,可能还会出现新的VSCode红线。处理方法是先判断Keil是否也编译失败;如果Keil能过,只有VSCode红,那通常就是IntelliSense兼容问题,补includePath或补一个兼容define即可。
批量处理时踩的坑
我最开始把一个已经消除红线的c_cpp_properties.json复制到其他例程,然后直接做字符串替换,结果发现有些配置仍然指向原来的旧例程。原因是JSON里的反斜杠有转义,直接字符串替换容易失败。正确做法是按JSON解析文件,逐项读取includePath,把每一项里的例程路径替换成当前例程路径,再写回JSON。
最后需要做校验:每个例程根目录都应该有自己的.vscode\c_cpp_properties.json;每个includePath都应该指向自己的例程目录,不能误指向其他例程;每个配置都要包含AC5 include路径,并且包含USE_HAL_DRIVER、STM32F407xx、__CC_ARM这些关键宏。否则可能看起来红线少了,但跳转会跳到别的例程,后面更麻烦。
最终怎么使用
现在日常使用方式比较简单:打开某个例程的.code-workspace,在VSCode里写代码,按F7编译,按Ctrl+Alt+F7重新编译,按Ctrl+Alt+D下载。下载和编译底层仍然走Keil,所以不需要重新发明构建系统。
如果只是改.c/.h里的业务代码,基本可以一直在VSCode里完成。如果要新增源文件、改include目录、改全局宏、改优化等级、改链接脚本、改下载器或Debug配置,还是应该回Keil里改,因为Keil工程仍然是唯一权威来源。VSCode在这里不是第二套工程系统,而是更现代的编辑器和操作入口。
VSCode迁移还有一个额外好处:Git/GitHub体验会自然很多。可以直接看文件变更、逐行diff、提交历史、分支状态,也更方便接入GitHub做版本管理。嵌入式工程很容易陷入“最终版”“最终版-可用”“最终版-真的可用”这种压缩包备份方式,迁到VSCode之后,代码管理会更接近正常软件开发流程。
AI与人类协同复现本文建议
建议由人类完成的工作:
1、安装VSCode(新建Profile)、Codex(建议用桌面端)、Keil(手动配置好烧录器和编译器设置)
2、提供一套验证过(编译烧录正常)的例程及相关硬件
建议由AI完成的工作:
1、批量生成或修正 .code-workspace、.vscode/c_cpp_properties.json
2、批量设置烧录器和编译器
3、VSCode红线问题
4、找出所有.uvprojx/.uvoptx工程,从基准工程提取AC5、J-Link、下载后运行等配置并批量同步
结束语:
这次迁移之后,我对Keil和VSCode的关系有了更清楚的认识。Keil不一定要被完全替代,至少第一阶段没必要强行CMake化或切GCC。对于已有Keil工程,更稳妥的做法是保留Keil工程体系和调试下载能力,把代码编辑、搜索、Git管理和AI Coding迁移到VSCode。
这套方案的好处是风险低,老工程不用大改,团队里继续用Keil的人也不受影响,而我自己可以在VSCode里获得更好的编辑体验和AI辅助能力。当然,如果以后项目需要跨平台构建或更标准化的工程系统,仍然可以继续往CMake、GCC、clangd、J-Link GDB Server这些方向走。但对于“已有Keil工程先迁到VSCode借助AI写代码”这个目标来说,Keil Assistant这条路已经足够实用。
ps:本文由GPT5.5根据调试上下文提炼书写,经由本人二次审核校对。如需Keil迁移VSCode建议直接将本文(或网址)让Codex阅读即可,不建议手动处理。
pps:Codex将我对AI的理解提升了一个台阶,以前我使用GPT/Claude Web端辅助代码书写,大部分时间浪费在复制粘贴文件代码,费时费力。
自从今年2月接触到Codex和Claude CLI之后发现编程竟是如此美妙,数天时间即可搭建符合我要求的精美前后端页面,AI 自动化爬虫省去了大量人工反复调试的烦恼(需要定好验收标准,如需要抓取到哪些元素并给出元素样本值构建测试集),ESP32环境监测站,手机备忘录,各种浏览器和PC插件,乃至最近搞软路由、个人资源站(IPV6+NAS+树莓派),Codex日常提升我的AI的边界认知。
真诚建议还没用上Codex(建议用官号(其实算下来用中转低价api也没便宜多少,而且feature被严重阉割)的朋友尽早体验下。
虽然我前面鼓吹了一波Codex,但在探索未知领域时建议先手动查找(主要是因为原始文章信息量一般更大更全,大概率图文并茂,现阶段Codex给出的未知领域教程基本以纯文字为主,对进入未知领域不利(无吸引点,容易让阅读者分神))下信息(或者让Codex找,人工阅读原始信息)建立粗糙的认知模型,以便在遇到偏门的问题时可以手动介入。anyway,我想表达的是,在完成(探索)未知的事情前,最好先建立到即使不借助AI,也能大致独立推进和排错的程度。
总的来说,对目标领域理解越深的人,使用AI越容易被放大,理解越浅的人,如果完全依赖AI,反而可能更容易被误导。高效使用AI的前提是人仍然有基本的判断,验收标准和必要的手动兜底能力。
END