从流水灯到量产固件:Vibe Coding 帮我重构了嵌入式开发的工作流
如果你也是嵌入式开发者,过去一年半应该跟我一样,经历了一种很微妙的职业焦虑变化。2024年初我第一次听说 Vibe Coding 这个词,当时嗤之以鼻,觉得这不就是“用AI写代码然后祈祷它能跑”吗?直到我在一个电机驱动项目里被三份寄存器手册的勘误表折磨到凌晨两点,我才开始认真审视这件事。到现在,我带着 Vibe Coding 工作流完整交付了6个量产级固件项目,涵盖电机控制、传感器融合、低功耗蓝牙外设和一块带FreeRTOS的采集板。我想把这些心得掰开揉碎了写下来,特别是结合“嵌入式vibe coding”这个方向上被讨论得最多、也最容易踩坑的地方。
这篇文章适合两类人。一类是和我一样的嵌入式工程师,想搞清楚 AI 辅助编程到底能不能用在固件开发上,边界在哪里;另一类是刚接触 Vibe Coding 的软件开发者,想知道这套工作流在硬件约束下会有什么不一样。我会从工具链选型、提示词结构、代码审查、陷阱排查、量产经验这几个维度,把我这一年的真实体验——包括翻过的车和填上的坑——全都讲清楚。
1. 内容整体设计与思路拆解
1.1 Vibe Coding 到底是什么,和“用AI写代码”有什么本质区别
Vibe Coding 这个词最早是 Andrej Karpathy 提的,原意是“跟 AI 一起写代码,让代码跟着氛围走”。听起来很玄乎,但拆开看核心就两件事:描述意图而不是描述语法,用对话驱动而不是逐行手写。在嵌入式场景里,这个理念有一个致命前提——你不能真的“让氛围走”,因为硬件不会给你模糊空间。寄存器就是那个值,时序就是那个周期,一个 volatile 漏了就是会跑飞。
所以我在嵌入式场景里理解的 Vibe Coding,和 Web 开发者在 React 项目里那种“帮我做个瀑布流卡片”完全是两码事。我的定义是:用结构化描述把硬件约束、业务逻辑、性能预期全部喂给大模型,让它生成可审查、可追溯、可验证的底层代码。听起来像高级版的模板生成?对,一半是,但另一半是它在很多细节上的确超出了我的预期。
我举个例子。一个 I2C 从机驱动的状态机,传统写法是手撸枚举、switch-case、超时重试。但它的状态迁移逻辑如果写成文字描述——“主机可能在接收 ACK 失败后重发 START,此时从机需要保持 SCL 拉低直到主机释放”——模型生成的框架往往比你临时想的更完整,因为它从训练数据里见过无数类似的 IP 核规格。当然前提是你要把时序要求讲清楚,所以 Vibe Coding 在嵌入式的第一步,是练好“用英文写需求规格”的功夫。
1.2 为什么嵌入式和通用场景的 Vibe Coding 完全是两套逻辑
通用软件里,AI 写错一个 API 调用最多崩一个页面,你可以热更新,用户骂两句就完事了。嵌入式里,AI 写错一个 GPIO 配置可能导致两块板子短路然后烧掉一颗价值 80 块的传感器。这个差异太本质了,直接决定了工作流的构建方式。
我总结下来,嵌入式 Vibe Coding 跟应用层相比有五个截然不同的约束:
- 资源边界硬性:Flash 就 128K,RAM 就 32K,模型不知道你的链接脚本里塞了什么东西,它给出的代码必须经过体积和栈深度的验证。
- 外设寄存器的不可推理:模型记住了很多芯片手册,但同一系列的芯片外设寄存器差异巨大,不能靠“它应该知道”来解决。
- 时序的不可讨论性:中断里不能放延时,DMA 描述符不能被 CPU 碰,这些不是“好的实践”而是“物理定律”,模型容易想当然。
- 调试手段受限:没有 print 到云端,没有 source map,出问题就是看波形、看寄存器转储、看逻辑分析仪。
- 安全等级要求:很多固件跑在医疗器械或者工业控制器上,代码必须能通过静态分析、MISRA 检查、同事 code review。
所以我会说,嵌入式 Vibe Coding 的核心不是“让 AI 帮你写代码”,而是“让 AI 帮你把规格变成初步实现,然后你以审查者的身份去掌控一切”。你的角色从打字员变成了架构师、审查员、测试工程师。
1.3 这一年半我走的三阶段路线:从“AI 帮我补全”到“AI 帮我设计”
回头看,我的 Vibe Coding 实践可以分成三个阶段。第一个阶段是 2024 年上半年,那时候我用 AI 干的最多的事情是“帮我写个 CRC16 查表法的 C 函数”或者“解释一下这个 linker script 的 ORIGIN 和 LENGTH 是什么意思”。这个阶段其实还停留在“高级搜索”的层面,省了些查资料的时间,但谈不上改变工作流。
第二个阶段是 2024 年下半年,我开始把 AI 输出的代码直接接到野指针调试、外设配置这些真正的项目任务上。最明显的转折点是那个电机驱动项目,我用一段非常详细的提示词让 AI 生成了整个 S 曲线速度规划器的骨架,然后只花了几个小时调试就接上了闭环。从那时候起我才意识到,AI 生成不是不可用,而是取决于你喂进去的约束条件够不够具体。
第三个阶段是 2025 年,我开始形成自己的方法论,并且在团队里复制这套流程。我现在会把一段需求式的提示词当成“数字设计文档”来对待,AI 生成的代码当第一版草稿,然后用编译器警告、静态分析工具、单元测试、板级验证四层过滤,合入主干。这个流程走了三个量产项目,稳定下来了。
2. 工具链选型与配套方案解析
2.1 LLM 选择:Claude 对话为主,开源模型做离线兜底
这一年半我试过五六款模型,目前的主力是 Claude 的对话模型处理复杂架构设计,配合开源模型做本地敏感代码的补全。选择逻辑不是看排行榜分数,而是看三件事。
第一,上下文窗口够不够装下完整的外设驱动文件。嵌入式代码里一个驱动往往有上千行,包含寄存器定义、状态机、回调、中断处理,如果模型记不住文件头部的类型定义,后面就会乱写类型。Claude 的长上下文用起来确实稳。第二,对芯片底层知识的覆盖度。有些模型在通用编程上很强,但你让它写 STM32 的 LL 库调用,它会把 HAL 的句柄和 LL 的寄存器地址混着用,这种错误非常隐蔽。第三,代码补全和对话式生成的平衡。我用下来的体会是,补全类工具适合在函数内部帮你填逻辑,对话式 AI 适合生成完整驱动骨架和对整个文件做重构。两者定位不同,别拿一个干另一个的活。
我有一个小习惯,凡是涉及 NDA 的代码,我不传完整文件,只传去掉了业务逻辑的骨架和类型定义,让模型补齐机制部分。凡是完全公开的芯片手册代码,我才会完整地在云端对话里做生成和重构。拿不准的时候就用本地模型跑一遍,虽然质量略低,但胜在安全。
2.2 嵌入式场景下的上下文工程:怎么把“半本书”喂给 AI
Vibe Coding 里术语叫 context engineering,我觉得在嵌入式领域这个比提示词技巧重要一个数量级。你不可能把整个 HAL 库丢给 AI,几千个文件它根本处理不过来。我总结了一套“上下文四件套”的打法。
套件一是芯片手册裁剪版。拿 STM32F103 举例,我这里说的不是把参考手册 PDF 丢进去,而是把你要用的外设章节的关键参数提取成一段文字,比如“TIM2 是 32 位定时器,APB1 总线,时钟最高 72MHz,预分频器 16 位,PWM 模式是 PWM1 和 PWM2,输出极性可配置”。这样的文字描述模型理解速度比 PDF 快十倍。套件二是现有代码骨架,头文件引用、宏定义、类型别名、硬件抽象层接口,这些让它作为生成的约束。套件三是编译环境信息,编译器是 GCC 还是 IAR,C 标准是 C99 还是 C11,有没有开启 LTO,会影响代码风格。套件四是明确的反例清单,告诉模型“这个项目里禁止使用动态内存分配,禁止在中断回调里调用 HAL_Delay”,这种负向约束往往最有效果。
有一次我把四个套件准备好然后跟 AI 说“请生成一个基于定时器输入捕获的脉宽测量驱动,中断服务函数里面不要加任何阻塞操作”,它给出的代码我看了一眼,中断函数里干干净净,状态机放在外面轮询,我很满意。反而是我后来尝试给 AI 更多自由度让“你自由发挥”,它给我在中断里加了一个浮点数除法,我花了一晚上才定位到那个中断延迟问题。
2.3 代码生成质量的关键变量:提示词的“硬件描述力”
很多博主在分享 Vibe Coding 时强调“把你的需求说清楚”,但到嵌入式领域,“说清楚”的门槛变得非常高。因为一个软件需求可以是“用户登录后跳到首页”,一个硬件需求则是“SPI 时钟在空闲时保持低电平,第二个边沿采样,数据帧长度 16 位,MSB 在前,操作 CS 引脚时需保持 MISO 线路不上拉”。
我把这种能力叫做提示词的“硬件描述力”,它由三个维度组成:引脚关系、时序要求、异常处理策略。我自己整理了一个模板,每次写提示词都会按这个结构来:
- 硬件环境:芯片型号、频率、编译工具链、目标跑在哪个外设上
- 功能需求:要完成什么协议、什么算法、什么状态迁移
- 时序约束:哪些环节有时间上限、哪些操作不能在中断里、时钟源是什么
- 资源残留:哪些字段必须静态分配、哪些全局变量是必须共享的
- 空指针与出错行为:异常时是保持静默、置错误标志、还是触发看门狗复位
这个模板第一次用时 AI 生成的代码质量和以前“帮我写个 ADC 采样驱动”对比天差地别。ADC 那个需求我写了八行描述,生成代码里它居然自动加了采样校准,还考虑了采样保持时间不够的问题。这就对味了——嵌入式工程师要的不是“代码生成器”,是“懂行的结对编程搭档”。
3. 实操过程与核心环节实现
3.1 一个完整的例子:用 Vibe Coding 生成可复用的软件定时器模块
原理讲完,我拿一个实际跑在量产产品上的模块来演示整个实操流程。这个模块是软件定时器,功能是在没有硬件定时器空闲通道的情况下,用系统 tick 来实现多个定时回调任务。
我不会直接丢一句“帮我写个软件定时器”,而是先准备好上文说的四件套,然后按模板写提示词。核心提示词结构如下:
硬件环境:STM32G0B1,主频64MHz,使用HAL库,C99编译,无RTOS 功能需求:实现一个软件定时器模块,支持周期模式和单次模式,最多16个定时器 时序约束:Tick来源是Systick 1ms中断,回调不能在该中断上下文直接执行 资源约束:不使用动态内存,所有对象静态分配,回调注册在调用时完成 异常行为:定时器溢出时忽略该次事件,不影响其他定时器AI 生成的第一版结构其实很标准,包括一个静态数组存 Timer 对象、一个链表串空闲节点、注册接口、启动停止接口、Tick 处理函数。但我在 review 时发现了三个问题:第一,数组固定 16,溢出时没保护;第二,回调在中断上下文直接执行,不满足我的约束;第三,从头遍历查找 Timer 是 O(n) 复杂度,在 1ms tick 里做遍历虽然不至于出大事但很蠢。
我第二轮反馈给 AI:“请修改:注册失败时返回错误码;Tick 处理只标记 pending,在主循环中统一分派;增加一个计数器记录当前活跃数,避免遍历。模型给出的第二轮代码就非常接近生产可用了。我补齐了边界保护,加了 unit test 用例,写完整个模块不到三个小时。”
从这次实操我能提炼一个观点:Vibe Coding 真正的杠杆不是一次生成的准确性,而是多轮对话中逐步补全约束带来的增量改进。AI 就像一个基础扎实但缺乏项目背景的初级工程师,你 review 它的代码就像带新人,只是它的修改速度比人类快二十倍。
3.2 外设驱动生成的正确姿势:为什么要给 AI “手绘”时序图
外设驱动是嵌入式固件里最需要精确生成的部分,也是最容易翻车的部分。我踩过最大的坑是让 AI 生成一个 1-Wire 总线的时序驱动,模型给出的代码里把恢复时间算了三分之二,导致一批温湿度传感器读数间歇性错误。
那次以后我养成一个习惯:复杂时序协议先在 ChatGPT 或者 Notion 里用文本画一个时序轴,把高低电平变化按时间顺序列出来。我不会让它画图,而是用文字描述每个阶段的持续时间、容差范围。比如 1-Wire 的初始化时序,我会写清“主机拉低 480us 以上,释放并等待 15-60us,从机应答拉低 60-240us——注意从机位于开漏总线时,1-Wire 项目使用强上拉,因此高电平的上升沿较快。时序容差和 GPIO 驱动能力必须一起检查。”这样把机械描述喂进去,生成的代码里延时参数、循环计数的换算就能对上。
还有一个技巧:把逻辑分析仪抓到的实际波形转成文字描述,比如“CS 下降沿后 SCL 经历了 5 个脉冲,其中第 3 个脉冲的 MISO 数据位为低,对应字节地址的 bit2”。这种真实的“行为描述”让 AI 生成的解析代码比对着手册手写更贴近实际硬件行为。我用了这个方法修复一个困扰团队两周的 EEPROM 读错误问题,AI 从波形描述里反推出地址自增位没有在发包前设置,换成人类工程师对着数据手册看到眼瞎也不一定找到。
3.3 从生成到板级验证:我的四层过滤流程
AI 生成的代码,不可能直接烧进单片机就说“跑起来了”,任何声称可以的人都是在骗你。我这一年半形成了一套四层过滤流程,现在团队里已经固化了。
第一层叫编译期过滤,让编译器开启 -Wall -Wextra -Werror,把警告当错误处理。AI 生成的代码经常有未使用的变量、隐式类型转换、函数指针类型不匹配这类问题,这一层能清掉三分之一。第二层叫静态分析层,我跑 clang-tidy 加 cppcheck,结合项目定制的 MISRA-C 规则子集,重点检查指针算数、资源泄漏、可疑的类型转换。这一层会再干掉一部分潜伏问题。第三层叫单元测试层,PC 上编译用宿主测试框架跑纯逻辑模块,比如 CRC、协议解析、状态机转换。嵌入式代码只要做到硬件抽象隔离,大部分逻辑都可以在 PC 上验证。第四层叫硬件验证层,放到真实芯片上跑,用逻辑分析仪和示波器验证时序、电平、协议交互。
这个流程跑顺了以后,AI 生成代码的合入速度非常快。我有一个经验数字:人工写的驱动板级调试通常要 2-3 天,AI 生成加四层过滤一般是 1 天左右,前提是你提示词写得好。但要注意,这个时间优势主要体现在驱动类、协议类、算法骨架类的代码上,一旦涉及复杂业务逻辑在多个任务间交互的模块优势就缩水了。
4. 踩坑实录与排查方法总结
4.1 Vibe Coding 在嵌入式里最容易犯的六类错误
过去一年半我把 AI 生成的代码中遇到的高频错误整理成了一个“黑名单”,每一条都是真实的板级事故。
第一类是寄存器位定义张冠李戴,模型容易混同相近系列芯片的寄存器布局,比如把 F0 系列的外部中断配置方式和 F1 系列搞混。这种错不跑起来根本看不见,只有实测外设不工作才暴露。第二类是中断上下文认知缺失,模型知道中断服务程序必须短小,但它不真正理解你的外设中断标志何时被硬件置位、何时清除。第三类是volatile 漏标,多任务共享的全局变量没标 volatile,编译器优化后在 Release 模式下能看到错乱状态。第四类是字节序和位域假设,不同平台的结构体对齐和位域分配不同,AI 不知道你的 ARM 默认小端还会做 4 字节对齐,很容易生成在 x86 模拟器上良好但在 ARM 上爆炸的代码。第五类是外设初始化顺序问题,有些芯片要求先使能时钟再配置 GPIO,顺序反了系统就 HardFault。这种错误模型很难自己规避,必须靠上下文约束和人工 review。第六类是超时处理不当,模型喜欢写“while(wait_flag==0);”这种一旦硬件异常就死循环的代码,正确做法应加超时看门狗和错误恢复路径。
这个黑名单我一直存在项目笔记的第一页,每次让 AI 生成代码后都对着这六条过一遍。效率提升非常明显,因为 AI 不会长记性,所以人必须替它长记性。
4.2 实测中最隐蔽的三个“幽灵 Bug”复盘
光列类型太抽象,我挑三个实际复现的 Bug 来说,它们都痛苦到让我想回去手写代码,但也正是这些 Bug 让我真正理解了 Vibe Coding 的能力边界。
第一个是 DMA 描述符的缓存一致性问题。AI 帮我写了 ADC 多通道 DMA 采集代码,在 SRAM 里建了一个 buffer,DMA 不断写入,主循环读出来做滤波。逻辑上完全没问题,但跑起来采集几个小时后数据开始出现周期性跳变。最后定位是 D-Cache 没有做 invalidate,DMA 写的数据被缓存掩盖,读的是陈旧值。这个 Bug 之前纯手写我也会踩,原理不是 AI 的锅,但它提示我——在带 cache 的 MCU 上,AI 生成的 DMA 代码必须经过一轮 cache 维护逻辑的专门 review。
第二个是浮点运算的可重入性问题。某个传感器融合算法被放在了中断上下文里,有个临时变量经过浮点寄存器传递,被更高优先级的中断打断后丢掉了上下文。这个问题只在打开 FPU 和嵌套中断才会出现,AI 从生成的代码里完全看不出来,因为 C 代码层面没有语法错误。解决方式也简单,把浮点运算挪到主循环,中断只置标志量。但这类问题是嵌入式 Vibe Coding 独有的,因为通用软件开发根本不关心中断嵌套和 FPU 状态保存。
第三个最气人,是 I2C 从机地址遗留问题。AI 很贴心地帮我加了“重试失败后复位从机”的逻辑,但它复位完后没有释放总线,SDA 被拉低,导致主控端看到的总线一直忙。排查过程持续了整整一天,最后用逻辑分析仪看波形才发现。这个 Bug 的深层原因是 AI 对硬件状态恢复的理解是“软件层”的,它不知道硬复位会让 I2C 外设保持内部状态直到下一次时钟边沿。现在我对所有“复位”、“恢复”、“清理”类的 AI 代码都会格外审查硬件层面的状态残留。
4.3 提示词写错了,方向就错了:AI 错误的归因分析
经常有人抱怨“AI 生成的嵌入式代码垃圾”,我一开始也这么觉得,但后来复盘发现大半问题出在提示词。如果你的提示词是“帮我看下这段代码有什么问题”,AI 只能做表面审查;如果你把具体的硬件行为、期望输出、观测到的异常都描述进去,AI 的归因能力会大幅增强。
我举个典型例子。一次 LORA 通信不稳定,我直接把代码丢给 AI 问为什么,它给出 5 个可能性全部偏软件。当我补充“信号强度指标 RSSI 正常但误码率升高,且多发生在温度超过 35 度时”之后,AI 立刻关注到可能是射频匹配电路的温度漂移,虽然它不能改硬件,但它建议我在固件里增加对接收 AGC 增益的微调补偿。你看,给 AI 喂上下文不是“教会它知识”,而是“帮它缩小假设空间”。
这一年半的实践让我养成了一个习惯:每次找 AI 排查问题之前,先自己花十五分钟把现象、环境、变化量写清楚。这个过程本身就是一次很好的排错练习,而且能显著提高 AI 输出质量。如果你的现象描述只有“不工作”三个字,那谁都帮不了你。
5. 能力边界、团队协作与未来演进
5.1 哪些需求不适合用 Vibe Coding 做?我的“红线清单”
虽然我算是 Vibe Coding 的践行者,但我心里有一条很明确的红线清单,碰到这些内容我会直接关掉 AI 自己动手。
红线一是安全关键路径,比如医疗设备的主控逻辑或工业安全回路,这类代码需要形式化验证方法和极强确定性,AI 的统计式生成无法提供证明。红线二是极端优化场景,当你需要把一个算法压进最后 200 字节 Flash 或者把循环优化到精确周期时,AI 生成的常规代码往往差得很远,手写汇编级别的优化仍然不可替代。红线三是遗留代码深层修补,一个 20 年历史的代码库里有大量隐式约定、全局状态依赖和“反模式”,AI 模型对它理解很肤浅,生成的补丁可能会符合语法但与运行时行为相悖。红线四是不可复现、不可验证的改动,如果这次改动没法通过单测或者板级复现验证,我一定不信任 AI 的输出。
这条清单帮我在团队争议时快速决断。Vibe Coding 不是银弹,它是一把非常好用但需要有经验的人握住的刀。
5.2 从个人实践到团队协作:让同事的代码审查模式升级
Vibe Coding 逐渐普及后,团队协作模式也在我这一年半里发生了微妙变化。以前 code review 是两人坐在一起看 diff 逻辑,现在更常见的是一个工程师拿着 AI 生成的代码和四层过滤报告给我看“这版我 review 过,风险点在我可控的范围”,然后我们从架构设计和异常路径上再强化审查。
这个模式能跑通的前提是团队里每个人都能读懂 AI 生成代码的“意图”并且有能力做方向性修改。我带的工程师经过几个月的训练,基本形成了“先让 AI 生成骨架,再自己动手填核心算法,最后反向 review AI 的遗漏”的习惯。效果体现在任务估算上,原先一个驱动模块估 5 天,现在平均 2-3 天,而且 review 时的高价值讨论更多了,因为低级错误都在前几层过滤掉了。
但有个副作用我必须提醒:代码归属感和系统整体理解责任感被稀释了。以前手写代码的时候每个宏、每个中断优先级都有来龙去脉,现在 AI 生成后工程师对“为什么这么写”的理解会变浅。我在团队里强制要求每个合入主干的 AI 生成模块必须由当事工程师写一段“设计决策备注”来记录关键取舍,就是为了对抗这种理解稀释。
5.3 嵌入式 Vibe Coding 的下一个阶段:硬件在环调试和全仓上下文
刚过完的一年半我基本还处在“人主导、AI 辅助”的阶段,但工具链进化速度很快。我现在比较关注两个方向。一个是硬件在环调试和数据回流,AI 在生成代码后如果能直接读到板级验证时抓取的波形、寄存器转储、异常堆栈,它的自我修正能力会大幅提升。另一个是整个仓库级别的上下文工程,不再局限于单文件对话,而是让 AI 充分理解项目里所有驱动、协议、链接脚本和编译配置,生成的代码从一开始就天然兼容项目风格和硬件特性。
这个方向能不能实现取决于工具链的成熟度,但我们已经在做一些前期的私有协议和仓库约束整理工作。我预感未来半年到一年里,会有更多嵌入式开发环境把 Vibe Coding 从前置对话式工具升级为编译回环里的实时参与者,那时候我们的“review 型”工作流可能还要再变一次。
6. 我在实操中最珍视的心得与建议
如果只让我留下一段对嵌入式开发者同行说的话,我会说:别害怕 Vibe Coding,但别信仰它。
把它当成一个精力极其充沛、知识面极广但完全不了解你硬件约束的初级工程师。你跟它合作的正确姿势是你负责定义边界、决定方向、做关键取舍,它负责快速执行机械性工作、提供不同实现思路、加速探索过程。这个定位一旦想清楚,你就能在效率提升和代码质量之间找到自己的平衡点。
最后分享一个我到现在仍在坚持的小习惯:每次用 Vibe Coding 完成一个模块,我都会把提示词和生成的代码存成一个“提示词快照”,隔两周回过头来对着板级现象重读一遍。这个习惯救了我很多次——因为有些 bug 当时以为是 AI 的锅,实际上是自己的需求描述里存在一个隐蔽的时序矛盾。当你能区分问题是模型能力问题还是自己的表达问题时,Vibe Coding 才开始真正变成你的生产力,而不是一个偶尔好用的玩具。