过去半年Vibe Coding是我所在的嵌入式技术群里出现频率最高的词之一。看着几个做Web的同事用自然语言描述需求让AI把原型、接口、单元测试一口气写出来说不心动是假的。于是有一天我把一块开发板上的SPI Flash驱动丢给了同一个AI助手结果在十分钟里陆续收获了三次HardFault、一次芯片读回全零以及一次看起来像死循环的卡死。这不是段子而是我在嵌入式开发里把Vibe Coding当真以后被硬件世界狠狠教育的一段实测。这篇文章想认真聊聊我的看法Vibe Coding在纯软件圈为什么能流行到了嵌入式和硬件边界又为什么经常失效以及它到底能替嵌入式工程师干什么、不能干什么。1. Vibe Coding 在纯软件圈火成这样嵌入式为什么跟进不了1.1 “Vibe Coding”到底是什么Vibe Coding共鸣式编程/感觉式编程这个概念最早由前OpenAI研究员Andrej Karpathy在2025年初提出本意很直白你不去逐行读代码、抠语法而是把意图用自然语言说出来让AI编程工具负责生成、修改、补全你自己只负责看运行效果和“凭感觉”不断调整方向。整个过程中人的注意力从“代码本身”转移到了“需求表述”和“结果表现”上。在实际操作里Vibe Coding通常不是一个单独的软件而是由AI编程助手、CLI工具、编辑器插件以及一份写得很详细的需求说明文件共同组成的工作流。比如给AI一个仓库上下文告诉它“实现一个带超时重试的HTTP客户端”它会自动完成选型、写代码、补测试你只要跑一下命令看是否通过。很多人在搜索“Vibe Coding安装/下载”以为它是一个类似IDE的工具。严格说它不是它是一种编码方式背后是Claude Code、Codex CLI等工具的组合。真正重要的是工作流设计而不是某个安装包。1.2 纯软件场景为什么容错度这么高Vibe Coding能在Web、脚本、工具类项目里快速流行不是因为AI写出来的代码质量有多神而是因为这类场景有几个天然优势反馈闭环极短写错了浏览器直接报错、单测直接红、日志直接打出来。每轮错误都能快速暴露AI可以立刻修。环境和部署高度一致本地跑通的容器推到服务器上大概率也能跑出错有堆栈回滚也简单。资源和性能不是核心瓶颈多分配几十MB内存、多循环几次几乎不会影响系统稳定性。错误隔离性好一个接口挂了不会让整个物理设备崩溃最多是这次请求失败。我把这种容错度总结为“错误代价低”。在纯软件世界里AI犯错的代价通常只是多消耗几轮对话和一点CPU时间。人和AI来回拉扯、不断纠错整体效率确实很高。1.3 嵌入式工程师眼里看到的“热闹”和现实但嵌入式工程师看完热闹心里往往会咯噔一下。因为我们手里的东西是完全另一回事代码不是运行在几GB内存的服务器上而是运行在几十KB RAM、几百KB Flash的单片机里旁边还有电机、传感器、功率器件和一块可能正在走生产流程的电路板。我见过群里有人开玩笑Vibe Coding 让Web开发效率翻倍让嵌入式工程师多了一堆需要擦屁股的代码。这话虽然偏激但部分真实。最典型的现状是AI能帮你很快写出一段看起来很美妙的固件代码但这代码能不能在你这块具体板子上跑起来取决于一堆它根本不知道的外部条件——时钟树怎么配、引脚复用怎么选、DMA通道冲突没有、看门狗会不会在固件下载后直接复位、中断优先级是否踩了别的模块。嵌入式工程师真正的工作很多时候不是在“写代码”而是在“让代码适配一块具体的物理设备”。而物理设备是不吃“感觉”这一套的。所以Vibe Coding 的“共鸣”在嵌入式这里会经常变成“共振”——稍不留神软件和外设一起剧烈抖动。2. 硬件世界的基本盘AI 默认写不出能直接跑的单片机代码2.1 内存和资源是第一条红线我给AI的第一个任务很简单“写一个SPI Flash驱动支持读、写、擦除。”它给出来的代码第一版里用了malloc来申请一块缓冲区然后在函数里自由地调用memcpy。如果是在PC上这份代码一点问题没有但在裸机或RTOS环境下malloc首先意味着堆管理器要占内存其次意味着不可预测的分配延迟再次意味着碎片、堆溢出风险。很多嵌入式工程团队直接把动态内存列为禁用项不是没有原因的。第二个问题更隐蔽AI习惯性地把大数组放在栈上。一个1KB的局部缓冲区在一个默认2KB栈大小的RTOS任务里就是不折不扣的炸弹。有一次它生成的代码要做Flash扇区擦写缓冲区、状态标志、局部结构体堆在一起一上板就HardFault。我接上调试器看到PC指针停在memcpy顺着栈回溯才发现是栈溢出。我后来把这类约束直接写进Prompt禁止malloc/new、禁止大数组上栈、所有缓冲区由调用者传入或静态分配。AI生成的代码在结构上立刻“收敛”了很多。这个约束本质上是把嵌入式内存模型教给AI不然它就是按通用编程的默认习惯乱来。2.2 实时性和时序编译通过不等于行为正确嵌入式软件开发里最难看的一类问题是代码逻辑完全正确但放到系统里跑就不对。Vibe Coding生成的代码在这种场景下尤其危险因为AI是根据大量通用代码训练出来的它天然倾向于“顺序思考”而不是“并发思考”和“时序思考”。举个真实例子。它帮我生成了一个读取温湿度传感器的函数逻辑很清晰发启动命令、轮询等待转换完成、读数据。坏就坏在那个“轮询等待转换完成”——它用一个while循环死等一个状态位。如果传感器I2C通信异常某个状态位永远不会置位这个while就成了死循环。在裸机小系统里这里有看门狗的话会不断复位没有看门狗整个设备直接卡死。我接入逻辑分析仪后看到的现象是I2C总线上一片死寂CPU却全速空转。这类问题编译器不会报错、单测也可能测不出来因为状态位在仿真环境里可以被完美置位。只有当代码运行在真实硬件上、遇到真实噪声和时序偏差时才会暴露。我总结的一句话是AI能生成“逻辑正确的代码”但生成不了“时序正确的系统行为”。嵌入式工程师的核心价值之一就是给代码加超时、加容错、加状态机保护把这些时序风险摁住。2.3 寄存器、位域与勘误表AI 没有见过的隐藏知识如果说内存和实时性还属于“代码层”那寄存器和外设控制字就是纯粹的硬件信息了。这里我见过更多翻车场面。AI生成一个DMA配置把外设地址、内存地址配好却忘了通道优先级和传输方向位的组合限制或者生成结构体操作外设寄存器时没考虑位域的对齐和字节序。这类问题在代码审查阶段很难肉眼发现因为看起来每个字段名称都对得上但一上板就是数据错乱或总线异常。更麻烦的是很多芯片的参考手册有随后的勘误表Errata某些寄存器配置组合在实际硅片上是禁用的。AI不会去查勘误表它只会按“理想芯片”来写。我曾经让AI生成一个UART波特率配置函数。它把波特率分频值算得很漂亮但完全没有考虑该型号MCU的USART外设在某些时钟源下的分频粒度限制。结果就是配置完串口波特率偏差超过3%数据偶尔乱码。这不是AI蠢是它没有接触过这块芯片的真实行为。所以我现在要求AI提供任何寄存器配置代码时必须同时给出数据手册的寄存器编号和位域说明我逐行核对。2.4 回答一个热搜问题嵌入式 Linux 开发必须用 Ubuntu 吗搜索词里有个高频问题嵌入式Linux开发需要在Ubuntu下开发吗我的答案很明确不是必须但用类Linux环境确实省心很多。嵌入式Linux开发的核心是交叉编译工具链绝大部分发行版都基于Linux生态。你完全可以在Windows电脑上装WSL或虚拟机、Docker容器把Ubuntu作为一个编译环境跑代码照样能交叉编译、甚至通过JTAG连上开发板调试。不过需要注意这个问题的存在本身就是嵌入式和纯软件之间“环境耦合”的缩影。AI生成的构建脚本、CMakeLists、固件链接脚本都要和你的工具链版本、目标CPU架构、库的ABI匹配。你在Windows上生成一个引用了GNU libc路径的构建脚本到了Ubuntu交叉编译环境里可能路径完全对不上。所以别把“在Ubuntu下开发”当成Vibe Coding之后就可以绕过的部分环境匹配和依赖管理还是得人工把关。3. 嵌入式场景里值得 Vibe 的三个方向样板代码、测试桩与构建脚本3.1 帮助生成驱动和协议的状态机骨架我不是说嵌入式开发完全不能Vibe。相反有几个方向我用下来觉得收益很大第一个就是“有明确定式的代码生成”。比如I2C、SPI、UART驱动的初始化骨架Modbus RTU的状态机MQTT协议报文解析CRC校验表生成DMA描述符链表的填充逻辑。这些代码的结构在所有芯片上都大同小异只是寄存器名不同。AI见过海量同类代码生成的质量和速度远超手写。我一般会在Prompt里直接扔进去一段工程现有驱动的头文件风格然后要求它照着风格实现另一个外设的驱动。我实测下来AI生成这类代码能直接用的比例在六成以上剩下的主要问题集中在寄存器配置值、超时逻辑、以及对芯片时钟树的依赖。所以我的原则是骨架让AI写寄存器值我核对时序和中断保护我来补。这样既省了敲样板代码的时间又不会把核心安全逻辑交给一个不了解硬件细节的AI。3.2 让 AI 写单元测试与 Mock这笔投资非常划算嵌入式项目里单元测试长期不受重视原因就一个硬件依赖太强Mock外设麻烦。结果反而是这个问题AI帮了大忙。我试过让它为一个光线传感器驱动生成Unity测试框架下的单测文件。我提供的是接口头文件和一组真假数据AI自动生成了一套桩函数把传感器驱动依赖的I2C读写接口全部Mock掉还自动构造了“写入地址后无响应”“读到全0xFF”“CRC校验失败”之类的错误场景用例。整个过程十几分钟换我以前手写至少一下午。更妙的是因为AI生成的测试逼近使用我被迫把驱动改成了可注入的接口模式——所有外设访问都通过函数指针或弱函数实现。这在以前属于“有时间再说”的架构改进被Vibe Coding这么一推顺手就做掉了。现在我的工程里每个驱动模块都带一套纯主机环境可跑的单元测试CI里只要交叉编译不过或测试挂了直接红灯。3.3 构建脚本和 CI与硬件无关的“元工程”正适合 AI第三类是跟硬件没有直接关系的元工程CMakeLists.txt、Makefile、Dockerfile、CI流水线的YAML、烧录脚本、日志解析脚本。这些内容本质上是文本编排AI几乎不会踩硬件坑生成的规范性反而比大多数工程师手写的强。我最近把一个老项目的Makefile迁移到CMake整个过程基本就是给AI描述目录结构、依赖库、目标芯片型号和链接脚本路径。它生成的CMakeLists包含了交叉编译工具链、编译宏、头文件目录和链接选项我只需要微调几个绝对路径。另外嵌入式开发的日志分析通常很原始——我从串口抓回来的hex日志以前要写脚本去解析现在直接让AI写一个Python解析器加统计报告十分钟搞定。这类工作放在“Vibe Coding”的本质里其实特别合理它有明确的输入、明确的输出、没有外设不确定性AI犯错的代价很低。我的建议是如果你暂时不敢把核心驱动交给AI那就从构建脚本和测试桩开始先体会这套工作流带来的正反馈。4. 从一场“AI 写驱动翻车”到可复用的辅助开发流程4.1 完整的排障链路HardFault、时序错位与卡死在轮询前面提到的SPI Flash驱动翻车案例值得展开说说因为它几乎是一次完整的嵌入式AI辅助开发图鉴。第一轮AI生成的代码上电后直接HardFault。我接上JTAG打开调试器看到PC指针停在memcpy附近栈回溯显示调用路径来自一个局部缓冲区直接拷贝到DMA描述符缓冲区。检查后发现AI在栈上申请了一个64字节的数组做数据中转而这块CPU的DMA地址要求必须对齐到缓存行栈上的变量根本不能保证对齐。我先用属性强制对齐保留了AI的整体框架HardFault消失。这个过程其实不太费时因为HardFault的定位路径非常标准看PC、看栈回溯、找数组和指针。第二轮能跑起来但读回来的数据全是0xFF。这轮更麻烦因为代码逻辑“看着没问题”。我先用逻辑分析仪抓SPI的四根线发现CS片选信号在写命令之前就被拉高了时序不对。查原因是AI没有理解“操作Flash前先写使能命令WREN”它以为直接读就行。我翻着数据手册把命令序列补上读数据正常了。到这一步AI生成的代码已经改了将近三分之一但骨架确实保留了。第三轮一切正常但连续擦除大扇区后系统卡死。排查发现AI生成的等待擦除完成循环里没有超时一旦Flash在高温或低电压下变慢轮询就可能一直等不到BBB位置位。我给它加了个带毫秒计数的超时退出并且把超时之后的重试逻辑交给上层处理。到这里我才算真正能把这套驱动拿给产品用。整个过程花了两个晚上如果完全手写大概一个白天就能利索地做完。4.2 AI 代码过板前必须过的人肉评审清单经过这轮折腾我给自己定了一份AI生成代码的评审清单现在已经成了团队里的强制检查项检查项具体内容为什么容易翻车动态内存是否出现malloc、new、裸指针分配裸机/RTOS堆限制多默认被禁用栈上大数组局部数组是否超过几百字节任务栈可能只有2KB一压就爆死等轮询while(状态位)循环是否有超时退出硬件异常时状态位可能永不置位寄存器访问是否用volatile或设备访问宏编译器优化会干坏硬件访问对齐与字节序DMA缓冲区、结构体位域是否packed不同总线宽度下极易错位中断上下文是否在中断里调用阻塞API或系统调用优先级反向、延时抖动、死锁我不是让你拿着清单一条条去卡死AI的输出而是说在让代码上板之前应该以“AI会犯这些错”为前提去审。我的体会是这份清单比任何AI提示词工程都管用因为它把嵌入式的硬件现实翻译成了代码审查语言。4.3 我现在使用的“AI嵌入式”工作流现在我的操作流程已经稳定为六步每一步都有明确的人机分工人类定义接口头文件把外设抽象成init/read/write/ioctl确定数据类型、返回值、错误码和生命周期。人类提供上下文包芯片头文件路径、一个已有驱动样例、寄存器速查表哪怕是数据手册扫描页以及几条硬性约束。AI生成实现体要求它实现.c文件并在Prompt里明确禁动态内存、禁大数组上栈、所有轮询加超时。人肉评审拿着数据手册逐项核对寄存器配置跑一遍我上面的检查清单。机器验证交叉编译、静态分析cppcheck等、主机侧单元测试全部通过后才能上板。上板分步测试先测基本通信再测异常注入断线、超时、错误返回最后才进业务联调。这套流程下来AI在我这里的角色从“写代码的人”变成了“写初稿的实习生”。它产出的代码框架质量很高但我的核心价值变成了判断初稿是否适配硬件现实、是否满足系统边界条件。这比纯手写省了大概三分之一的时间但该花的校验时间一点没省。5. 热搜词背后是职业焦虑应用层开发算不算嵌入式工程师该往哪走5.1 “应用层开发是不是嵌入式”为什么会成为热词搜索引擎里出现“应用层开发是不是嵌入式”这个高频问题说明大量从业者正在做嵌入式Linux应用层、Qt界面、网络服务和业务逻辑却不确定自己算不算嵌入式工程师。我的看法是嵌入式系统本身就是分层的应用层当然属于嵌入式的一部分。一个典型的嵌入式Linux产品从上到下是应用层、中间件、操作系统内核、BSP/驱动、硬件。你不能因为自己长期只写应用层的业务逻辑就说自己不碰嵌入式反过来如果你只碰业务逻辑对下层毫无感知那确实需要警惕因为你正在变成一个通用的软件工程师只是碰巧把程序跑在嵌入式板子上而已。区别在于嵌入式应用层工程师至少要理解下层的接口语义设备树节点、sysfs属性、中断信号、DMA缓冲、实时性约束。比如你用Qt写一个工业HMI界面调用SPI设备节点读取传感器数据如果你不知道SPI设备在某个时钟下会产生不确定延迟你就不会设计合理的刷新策略和错误重试。这些知识才是“嵌入式”三个字的含金量所在而不是你用什么语言、跑什么系统。5.2 分层能力图谱越靠近硬件AI 的可靠度越低我画了一张自己的能力评估表用来判断不同层次的嵌入式开发AI能帮忙到什么程度层次典型工作AI可生成代码的可靠度人工必须把关的重点应用层Linux C/Qt界面、业务协议、网络服务较高业务语义、生命周期、系统集成、资源泄漏中间件RTOS组件、通信栈、日志服务、OTA流程中等任务优先级、内存规划、故障恢复策略BSP/驱动寄存器配置、中断、DMA、时钟、电源管理较低寄存器值、时序参数、芯片勘误、功耗硬件方案电路设计、信号完整性、器件选型基本不能辅助电气特性、认证要求、成本这张表对我来说有两层意义。第一准备用AI之前先看自己工作在哪个层次决定对人肉评审的投入程度。第二职业规划上越往上层的开发Vibe Coding带来的效率增益越大但同时岗位的被替代风险也越大越往底层走AI越难以取代因为硬件现实和隐性知识的门槛根本不是自然语言Prompt能简单跨越的。尤其是汽车电子这种功能安全敏感领域AUTOSAR分层、ISO 26262流程要求代码可追溯、变更要经过严格的测试和文档归档。在这种环境里AI生成的代码可以作为初稿但要走到量产中间的路比普通消费电子长得多。嵌入式工程师在这些领域里不仅写代码还身兼系统安全、故障模式分析和验证策略设计这些都不是“Vibe”能覆盖的。5.3 Vibe Coding 时代嵌入式工程师的核心竞争点不变回到我最开始翻车的那个SPI Flash驱动。真正让它从“编译通过”走到“稳定跑完一万次擦写”的那部分工作——寄存器核对、超时设计、异常注入、看门狗配合、现场故障排查——每一步都来自工程师对硬件行为的理解和对失败的预判。AI替我写的只是一层很薄的骨架我没有被工具取代反而因为工具节省了体力劳动能把更多精力放在系统级问题上。这个时代对嵌入式工程师最友好的状态是把AI当成一个执行力极强但完全不懂硬件现实的初级同事。你要做的是教它规矩、审它的输出、在它搞不定的地方兜底。换句话说Vibe Coding解决的是“从需求到代码”的生产率问题但它没有解决“从代码到系统稳定运行”的工程问题。后者依然是嵌入式工程师最坚固的护城河。最后分享一个我自己的小习惯每次让AI生成代码前我会强制自己先写一个最核心的测试用例哪怕只是“初始化后寄存器复位值为默认值”这种弱断言。这个用例写下来AI的自由发挥范围就被框住了。对我来说这比任何复杂的Prompt模板都更接近Vibe Coding的正确打开方式——在充分享受自然语言表达效率的同时把硬件世界的确定性牢牢攥在自己手里。
