← 返回教程库

固件工程化:从"能跑的代码"到"放别人手里几个月不崩"

最后更新 2026-06-20
L5 · 产品化 ⏱ 约 16 分钟 🟢 软件/低风险
你将学到
  • 看清 demo 代码和产品固件差在哪几处,差距有多大
  • 给固件加上看门狗,让它卡死后自动重启
  • 用异常恢复和断网重连,让设备从故障里自己爬起来
  • 理解掉电保护、NVS 持久化、OTA 远程升级的价值和取舍

你的设备在桌上跑得好好的,灯按预期闪、数据按预期传,你拍个视频发朋友圈,很有成就感。于是你寄了一个给朋友。两天后他发消息:"你这玩意儿死机了,戳半天没反应。"你在自己桌上从来没遇到过。

这不是你运气差,这是几乎每个第一次做硬件的人都要撞的墙:demo 能跑,不等于产品能用。 你桌上那台之所以稳,是因为它在被你"伺候"着——网络是你家的、电源是稳的、出问题你随手就重启了。一旦它离开你的视线、进了别人手里,没人伺候,所有你没处理的边角情况全会冒出来。

这一节不教新的传感器、新的协议。它教的是一件更朴素也更值钱的事:怎么让你写的固件,丢给一个不懂技术的人,也能在他家里安安静静跑上几个月不用你管。这是 L5 产品化里最容易被跳过、却最决定"它到底是个玩具还是个产品"的一关。读这一节,最好你已经走过 L5 画 PCB,硬件那边的可靠性有了基础——固件的可靠性是另一半。


demo 代码和产品固件,差在哪

先把这条河看清楚。同样实现一个"读温度、传到手机"的功能,demo 和产品的代码差出一个量级,差的全是你平时不写的那部分:

  • demo 假设一切正常:WiFi 一定连得上、传感器一定读得到、电一定不会断。产品固件假设一切都会出错,每一步都得想"如果这步失败了,接下来怎么办"。
  • demo 死了就死了,反正你在旁边重启。产品固件得能自己从死里爬起来——卡住了自动重启、断网了自动重连、读数失败了自动重试。
  • demo 的配置写死在代码里,改个 WiFi 密码就重新烧一遍。产品固件得把配置存起来、能改,断电也不丢。
  • demo 没法升级,发出去就定型了。产品固件得留一条远程升级的口子,发现 bug 还能补救。
📌 说明

一个粗略但实用的判断:如果你的固件里没有任何 if (失败) 的分支、没有任何"重试"和"重启"的逻辑,那它大概率还是 demo。产品固件的代码量里,处理正常流程的可能只占一半,另一半全在伺候各种异常。

下面把产品级固件最关键的几处,逐个讲透。


要点一:代码结构与版本管理

第一道坎不在技术,在习惯。新手最常见的样子,是把所有逻辑堆在一个 .ino 文件里——WiFi、传感器、显示、业务逻辑全挤在一个几千行的 loop() 里。能跑,但三个月后你自己都看不懂,改一行怕动了别处,更别提丢给 AI 帮你看——它一次也读不完。

把代码拆开,按"一件事一个模块"分文件:网络一块、传感器一块、业务逻辑一块。每块对外只露几个清晰的函数,内部怎么实现别人不用管。拆完你会发现,找 bug、加功能都快多了,因为你每次只需要盯着一小块。

版本管理同样不能省。给每一版固件编个号(比如 v1.0.3),把版本号打进固件、开机时打印出来。这件小事在你做了 OTA 之后会救你的命:设备在远方出问题,你第一句要问的就是"它现在跑的是哪一版"。没有版本号,你连它该不该升级都判断不了。

💡 提示

从第一行代码就用 Git 管起来,哪怕只有你一个人。每改通一个功能就提交一次、写清楚改了啥。等你某次改崩了想回到"上周还好好的那一版",你会无比庆幸当初有提交记录。这不是给团队用的,是给三个月后的你自己用的。


要点二:看门狗——卡死了自动重启

这是产品固件和 demo 最硬的一道分水岭。

设想你的设备在某次读传感器时,因为一个你没料到的情况卡住了——代码停在某一行,loop() 再也转不下去。在你桌上,你看一眼没反应、伸手按下复位键就完事。可它在别人家里,没人会去按那个键,于是它就这么"死"在那里,直到有人发现、拔电、重插。

看门狗(Watchdog)就是替你按那个复位键的人。 它的原理简单到优雅:芯片里有一个一直在倒数的计时器,你的程序必须每隔一小段时间去"喂"它一下(行话叫喂狗,把计时器清零重新倒数)。只要程序正常运转,狗就一直被喂着、永远数不到零。可一旦程序卡死、没人喂了,计时器数到零——看门狗直接把芯片重启,设备几秒后自己满血复活。

ESP32 内置了硬件看门狗,这是它实打实的特性,可以放心用。用法的大致样子是这样(具体函数名、参数以官方文档为准):

// 示意:开机时设置一个看门狗,超时时间比如 8 秒
// 然后在 loop 里每一轮都喂一次狗
void setup() {
  // 初始化看门狗,设定"多久没喂就重启"的超时
  watchdog_init(8 /* 秒,示意值 */);
}

void loop() {
  doYourWork();      // 你的正常业务
  watchdog_feed();   // 喂狗:告诉看门狗"我还活着"
}

关键不在于背下函数名,而在于理解这个机制,以及喂狗位置怎么放:要放在"程序正常时一定会执行到、卡死时一定执行不到"的地方。如果你图省事把喂狗塞进一个就算程序假死也照样会触发的中断里,那看门狗就形同虚设——狗一直被喂,可你的主逻辑其实早卡死了。

🚧 避坑

看门狗最常见的翻车,不是不会用,而是用反了:超时设得太短,结果某次正常的耗时操作(比如一次较慢的网络请求)还没干完就被狗咬了重启,设备反复重启进不了正常状态。超时要留足余量,覆盖你最慢的那个正常操作。先把"什么是正常的最长耗时"想清楚,再定超时值。


要点三:异常恢复与断网重连

看门狗是最后一道兜底——它管的是"彻底卡死"。但更多的故障没那么极端,只是某一步暂时失败了:WiFi 断了一下、传感器某次读了个坏值、服务器没响应。这些情况下程序还活着,你不该直接重启,而该让它自己重试、自己恢复

这一点和你在 L3 学 WiFi 联网时埋的伏笔直接呼应。demo 里你大概率是开机连一次 WiFi,连上就再也不管了。可现实里 WiFi 会断——路由器重启、信号波动、别人家网络抢道。产品固件必须把"连接"当成一件需要持续照看的事:

  • 检查连接状态,发现断了,就自动尝试重连,而不是傻等。
  • 重连别死命猛冲。连不上时隔几秒再试,多失败几次就把间隔拉长(行话叫退避),别在断网时疯狂重连把自己和路由器都拖垮。
  • 读数失败给几次重试,传感器偶尔抽风读个坏值很正常,重试两三次再放弃,比一次失败就报错强得多。

核心心态就一句话:把每一个外部依赖都当成"随时会掉链子"来写。 网络、传感器、电源、对端服务器,没有一个是你能 100% 指望的。产品固件的稳,就稳在它对每一处"掉链子"都准备了下一步动作。


要点四:掉电保护与数据持久化

再设想一个场景:用户给设备配好了 WiFi、调好了几个参数,用得好好的。某天家里跳闸断了电,来电后设备一开机——所有配置全没了,又回到出厂状态,得重新配一遍。用户的耐心也跟着这次断电一起没了。

问题出在:你的配置只存在内存(RAM)里,一断电就清空。要让配置活过断电,得把它写进断电不丢的存储。ESP32 上有一块专门干这个的区域,叫 NVS(Non-Volatile Storage,非易失性存储),这是 ESP32 真实提供的机制,可以放心用。你可以把它理解成芯片自带的一个小小的"配置抽屉":

  • 用户配好 WiFi、设好参数,你就把这些值写进 NVS
  • 设备每次开机,先从 NVS 把上次的配置读出来,恢复到断电前的状态。
  • 配置变了再写回去。读写都很快,存的也就是些小数据(密码、开关、几个数值),不是大文件。

具体的 NVS 读写 API(命名空间、键值对的存取函数)以 ESP32 官方文档为准,这里讲的是该把什么存进去、什么时候存。判断很简单:凡是"用户配过、不想再配第二遍"的东西,都该进 NVS。 WiFi 凭据、用户偏好、累计的运行数据,都属于这类。

💡 提示

别把所有东西都往 NVS 里塞。它适合存小而关键、改动不频繁的配置。那种每秒都在变的实时数据(比如当前温度读数)没必要存——它本来就该是"实时"的,重启后重新读一次就有了,反而频繁写还会磨损存储。存"配置",不存"瞬时状态"。


要点五:OTA 远程升级,为什么值得做

前面四点让设备,OTA 让设备还能被你救

OTA(Over-The-Air,空中升级)指的是:设备不用插线、不用拆壳,通过网络就能把固件更新成新版本。这同样是 ESP32 支持的真实能力,你在 L3 接触过 OTA 的概念,到了产品阶段,它的价值才真正显出来。

想想没有 OTA 的处境:你发出去 50 台设备,散在 50 个人手里,某天你发现固件有个 bug——读数偶尔偏高。怎么修?挨家挨户上门、把设备收回来、插线重烧、再寄回去?这成本高到等于这个 bug 永远修不了。而有了 OTA,你改好代码、推一个新版本,设备们联网时自己就把更新拉下来装上了。一个能远程升级的设备,和一个发出去就定型的设备,是两种东西。

OTA 也不是没代价,做之前你得想清楚几件事:

  • 升级到一半断电怎么办?得设计成"新固件没装完、装坏了,能退回旧的那一版",不能升级失败就变砖。这通常靠预留两块固件区来实现,是 OTA 工程里最该认真对待的部分。
  • 怎么确认推的是对的固件?得能识别"这个固件是不是我发的、有没有传坏",否则升级机制本身就成了风险口。
  • 回到前面的版本号:没有清晰的版本管理,你根本不知道哪台该升、升到了没有。这就是为什么要点一里强调版本号。

具体的 OTA 实现(分区表怎么配、升级流程怎么写)以 ESP32 官方文档和成熟方案为准。这一节让你记住的是:OTA 是产品的"后悔药",留这条口子的成本,远低于将来没它时的代价。


量产时,固件怎么刷进几百台

前面都在说"一台设备怎么稳"。可当你要做的不是一台、是几百台,又冒出一个新问题:固件怎么高效地刷进这么多板子?

你自己玩的时候,是插上 USB、点一下上传、等它烧完——一台几十秒。可这套流程放到几百台上就崩了:你不可能蹲在那儿插一台、烧一台、拔一台,重复三百遍。量产烧录走的是另一套思路:

  • 批量烧录工具/工装:用专门的烧录器或夹具,把固件文件一次性、自动化地刷进板子,烧完自动校验通过与否,比手动 IDE 上传快且不易出错。
  • 出厂时一并写入身份信息:很多产品在烧固件的同时,给每台板子写一个独一无二的编号或密钥(写进前面说的 NVS 或专门区域),这样每台设备出厂就有了自己的"身份证",后续联网、OTA 都靠它区分。
  • 烧完即测:成熟的产线会把"烧录"和"测试"连起来——刚烧完就自动跑一遍基本功能自检,不合格的当场挑出来,不让坏板流到用户手里。

你做几台、几十台的小批量,未必用得上全套产线工装,但理解这套思路有用:它会反过来影响你怎么写固件——比如要不要预留写身份信息的位置、要不要在开机时加一段自检逻辑。为量产着想的固件,和只为自己跑一台写的固件,结构上是有区别的。


测试与老化:让它先在你这儿"熬"够

设备稳不稳,不是看它跑通的那一下,是看它连续跑很久的样子。很多 bug——内存泄漏、计数器溢出、某个几小时才触发一次的边角情况——你跑五分钟根本碰不到,得让它熬。

  • 长时间连续运行(老化测试):把设备插上电,让它一连跑几天,期间盯着它有没有变慢、死机、重启、读数漂移。一台能在你桌上稳跑一周的设备,到用户手里出问题的概率会低很多。
  • 测极端和异常情况,而不只是测"正常用":故意拔掉 WiFi 看它会不会重连、故意拔电再上电看配置还在不在、故意喂它一个坏数据看它会不会崩、把温度搞得很高很低看它读数还准不准。你在桌上多坑它一次,用户在家里就少崩一次。
  • 测够了再发:忍住"跑通了就赶紧寄出去"的冲动。多熬几天的成本,远低于发出去之后远程救火的成本——尤其是你还没做 OTA 的时候。
💡 提示

老化测试不用你一直盯着。让设备一边跑、一边把关键状态(运行了多久、重启过几次、有没有报错)记下来——可以打印到串口、存进 NVS、或联网传出来。第二天你看一眼记录,就知道它这一夜过得稳不稳,比你干瞪着它高效得多。


这几个坑,新手固件十有八九中招

后果 怎么避
没加看门狗 设备某次卡死后永远不醒,用户得手动拔电 加硬件看门狗兜底,在主逻辑里正确喂狗
内存泄漏 跑几小时到几天后内存耗尽,越跑越慢直至崩溃 老化测试盯着内存余量;谨慎使用动态分配,用完及时释放
没留升级口(无 OTA) 发出去才发现 bug,挨家挨户收回重烧,成本高到没法修 产品固件从一开始就把 OTA 纳入设计
配置不持久化 一断电就回出厂态,用户重配到崩溃 关键配置写进 NVS,开机读回
断网不重连 WiFi 抖一下就彻底掉线,再也连不回来 持续检查连接状态,断了自动退避重连
没有版本号 设备出问题,你不知道它跑的哪一版,没法判断该不该升 每版编号、打进固件、开机打印
🚧 避坑

这六条里,"没加看门狗"和"没做 OTA"是最致命的两条——因为它们一旦缺失,设备出问题时你完全无能为力:卡死了没人重启、有 bug 了没法远程修。其它几条还能事后补救,这两条缺了,等于把命运交给运气。所以哪怕项目再小,看门狗和 OTA 的口子,建议从设计第一天就留好。


动手挑战

别只读,挑一个动手把你现有的项目往"产品"推一步:

  1. 给你的项目加一个看门狗。 找到你的 loop(),在开机时初始化看门狗、在主循环里正确的位置喂狗(具体 API 查 ESP32 官方文档,不确定就把你的代码发给 AI 让它对照官方写法补上)。加完故意写一行死循环卡住它,验证设备会不会在几秒后自动重启——能自动活过来,你就真正给设备上了第一道保险。

  2. 进阶:把你项目里"用户配过、不想再配第二遍"的某个值(比如 WiFi 密码,或一个阈值参数)改成存进 NVS,重启后从 NVS 读回。然后拔电再上电,验证它还在不在。

💡 提示

卡住了就把你的 loop() 代码、用的板子型号、想加的功能一起发给 AI,让它对照 ESP32 官方文档帮你补看门狗或 NVS 的代码——但加完一定要自己拔电、写死循环亲手验一遍,亲眼看到它自己活过来,才算数。AI 帮你写,硬件替你判分。


小结 · 下一步

  • 你看清了 demo 和产品固件的分水岭:产品固件假设一切都会出错,每一步都准备了下一步动作。
  • 你理解了五个产品级要点——代码拆模块加版本号、看门狗卡死自重启、断网与异常自恢复、配置进 NVS 不怕断电、OTA 留住远程救火的口子。
  • 你知道了量产烧录、老化测试是怎么回事,以及它们怎么反过来影响你写固件的方式。
  • 你记住了六个高频坑,尤其"没看门狗""没 OTA"这两条最致命,最好从第一天就避开。

固件稳了,硬件成型了,你的项目离"能交到别人手里"只差一层壳。下一步:把电路装进一个能拿、能用、看着靠谱的外壳,看 L5 外壳与结构;想看自己处在整条产品化路线的哪一站,回 L5 产品化全景路线图 对一眼;觉得 L5 已经走顺、想往更进一步的方向看,瞄一眼 L6 进阶

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明