现在用 Cursor、Claude Code 这类工具写单片机代码的人很多,生成速度确实快,一段外设初始化几秒钟就出来了。但真烧到板子上,不对的概率比写前端高得多。前端跑在浏览器里,AI 和你看到的是同一个运行环境;单片机不是,代码跑在它没见过的板子上。我这一阵子用下来,翻车的地方很集中,就两三个,写出来给你对对号。
第一个翻车点:它不知道你板子上有什么
最容易翻车的是它根本不知道你的开发板上到底有什么东西。数据手册没有、引脚接口参数全是它自己猜的。
你跟它说用的是 STM32F103,它就按例程给你配置时钟,但你开发板的晶振焊的是 8M 还是 12M 它不知道,串口波特率设置时错的但编译不报错,烧录上去结果就是不对。这种问题代码 Review 一百遍也看不出来,因为逻辑本身是对的,错的参数在板子上。
型号相近的料还有更细的差别。同样是 F103,C8T6 和 RCT6 的 Flash 和 RAM 大小不同,引脚数不同,某些外设的挂载总线也不同。AI 给你的代码往往是从训练数据里最常见的那个型号抄的,你手上这颗是不是同一个,它不关心。
所以换一个开发板,这些全都得重新照着数据手册重新做一遍。这不是 AI 的问题,是这件事的信息本来就不在代码里,在你桌面上那块板子上。
第二个翻车点:它对时间没概念
第二个翻车的地方是时间。它对时间完全没有概念,写个阻塞延时代码随手就往中断里面塞,中断一卡死其它代码逻辑全部停止。仿真里看不出来,因为仿真不模拟时间竞争,板子上就是各种古怪的现象一起出现。
最典型的是数码管扫描显示。扫描显示每一位的点亮时间要精确到微秒级,切换位选的顺序也有讲究:先写段码再开位选,切换前要把上一位的段码清掉。AI 写出来的版本逻辑上完全正确,时序上全是窟窿,通电直接乱闪。这种问题我在 VFD 荧光管那篇里展开写过,从定位到调稳定花了很久,链接在文末。
按键消抖这种给出来的延时常数也一样,全是自己想的数值,10ms 还是 20ms 全凭它心情,跟主循环有没有冲突它完全不管。你的主循环周期如果是 5ms,它给你塞个 50ms 的消抖等待,按键手感立刻就坏了。
一个直接的判断办法:AI 生成的代码里所有 delay_ms() 这种调用,你都要停下来问一句这个数哪来的。答不上来的,自己查数据手册重定。
第三个:它不知道你工程的约束
这一条不算 AI 的错,但你得替它想着。它不知道你整个工程的约束,比如编译器还有多少空间。我那个 8051 的项目,Keil 评估版代码上限 0800H,我已经超限了,每次让 AI 加功能它都写得很大方,一个查表数组就把我顶出上限。空间预算这件事必须记在你自己脑子里,AI 不会主动帮你省。
类似的还有中断优先级的分配、哪些变量要加 volatile、串口接收缓冲开多大。这些是整个工程的决策,AI 只看得到你发给它的那几段代码。
我现在的分工方式
所以我现在的分工是:让 AI 只写业务逻辑,外设初始化这种自己来写,至少要自己过一遍。时钟、引脚、中断优先级这三样,对着数据手册确认没问题了才烧录进去。
业务逻辑指的是数据处理、状态机、协议解析这些不碰硬件寄存器的部分。这部分 AI 写得又快又好,错了也好改。串口一帧数据怎么切、一个命令怎么解析,让它来,省下的时间是真金白银的。协议解析的状态机写法我单独写过一篇,也是让 AI 按那个路子生成的,一次就过。
烧录前的核对清单就三项:时钟对不对、引脚有没有被复用占用、中断优先级有没有倒挂。这三样查完,剩下的翻车基本都能靠串口打日志定位,不会一上电就黑箱。
AI 写单片机代码这件事本身是划算的,翻车的原因不是它写得差,是有些信息它天生拿不到。把这些信息自己补上,工具就该这么用。