☰
嵌入式偶发Bug排查:串口、蓝牙与烧录的实战方法
2026/10/2 12:13:34 网站建设 项目流程

做嵌入式开发这些年,最怕听到的一句话不是“程序跑飞了”,而是“它刚才还好好的,现在又好了”。偶发 bug 就是这么个东西——它不会老老实实躺在你面前让你修,而是躲在一个你不知道的角落,隔三差五冒出来恶心你一下,等你架好示波器、拉好日志、一脸严肃地盯着它时,它就乖得像什么都没发生过一样。

这篇文章想聊的,正是三种最典型的偶发问题场景:串口假故障、蓝牙随机断开、烧录批次玄学。三种场景对应三个手段:换机排除、录屏取证、新旧批次对照。这三个方法我这几年在量产调试、客户现场支持和研发排障里反复用,每次查完回头看,最初的猜测基本全是错的,真正有用的恰恰是这些笨办法。希望能给同样被偶发 bug 折磨的同行一点参考。

1. 偶发 bug 为什么难缠:先解决“看不见”的问题

1.1 偶发 bug 的共性:证据链断裂

偶发 bug 难查,根本原因不是“难度”,而是“证据”。普通 bug 你手上至少有一条稳定复现路径,有 log、有报错码、有操作步骤。偶发 bug 什么都没有——故障出现的时候你不在场,等你到场它又恢复正常。

我遇到过一个很典型的案例:客户反馈设备串口每隔一两天就“死”一次,断电重启就好。开发组第一反应是查代码,怀疑串口中断服务函数有 bug,查了两周毫无进展。最后排查定位到电源模块在特定负载下输出电压跌落,偶发触发了串口芯片复位。这个问题靠盯着代码看是永远看不出来的。

所以排查偶发 bug 的第一原则:**先收集证据,再提出假设。**不要急着改代码、换硬件,先把现场抓下来。证据分为几类:软件运行日志、操作系统日志、物理状态(供电、接线、温度)、以及最容易被忽略的——人做了什么操作。后面几章讲的换机、录屏、批次对照,本质上是三条不同的证据收集路径。

1.2 三条黄金原则:不猜、不改、一次一个变量

第一条,一次只动一个变量。这是最基础也最容易被违背的原则。设备出了问题,很多人上来就顺手把线重插一下、参数调一下、固件升一下,然后问题“好了”。但你能说是哪个操作修好的吗?说不出。这就是无效排查,这次经验对下次没有任何复用价值。

第二条,记录一切,包括你觉得没用的。批次号、固件版本、接线方式、供电电压、环境温度、操作人、操作时间……现在觉得没用,排查到第三天可能发现唯一的线索就是最开始那个不起眼的记录。

第三条,不要把“时效性”当成“因果性”。设备烧录失败,你换了台电脑、换了根线、换了块板子,最后成功了,但到底哪一步起作用了?如果不做隔离对照,这次成功对你没有任何信息量,甚至可能是负面信息——它会让你误以为是某个环节的问题,实际上真正的元凶还躲在原地。

这三条原则看着简单,实际做下来大部分团队都会在某个环节破功。后面每个场景的排查步骤,本质上都是这三条原则的具体展开。

2. 串口假故障的换机排除:从“换一台就好”到“为什么这台不行”

2.1 什么是串口假故障

先定义一下“串口假故障”:表现上像是设备串口彻底坏了,但设备本身没坏,问题出在通信链路上的某个环节——可能是线材、可能是电平、可能是驱动、可能是供电。

典型表现通常这么几种:

  • 用串口调试助手打开端口,设备偶尔不回数据,偶尔回一半乱码
  • 刚上电正常,运行几分钟后串口无响应,重启恢复
  • 同一套代码在这台电脑上正常,换一台电脑就不行
  • 长时间不操作后第一次收发失败,第二次就好了

遇到这种情况,绝大多数人的第一反应是“设备坏了”,然后走换机流程。换机本身没错,但“换机排除”的目的不是把锅甩给某台设备,而是通过系统性的替换实验,把故障范围一步步缩小到某一个具体环节。记住,换机不是目的,缩小范围才是。

2.2 换机排除的正确顺序:从成本最低的换起

这里有个经验法则:换机顺序按“更换成本”从低到高排,同时每换一步都要有明确结论,不留模糊地带。

步骤更换对象成本判断依据
1USB 线 / 串口线最低排除线材接触不良、芯线内部断裂
2USB 端口(换一个口或换一台电脑)低排除端口供电不足、驱动冲突
3USB 转串口模块(换一个 CH340 / FT232 模块)中排除转换芯片自身问题
4目标设备(换一块同批次板子)高排除板级硬件故障
5整个测试环境(换电源、换负载、换示波器探针位置)视情况排除环境干扰与电源纹波

有人可能会问:为什么不直接换一块板子试,多省事?因为换板子成本高,而且一旦板子本身没坏,你会得到一个“新板子正常”的假结论,顺手把旧板子判了死刑退回厂家。厂家检测后告诉你“一切正常”,问题就被踢皮球踢回来了。

2.3 一个真实的 CH340 排查经历:换机之后还要追问为什么

去年一个量产项目,产品用的 CH340 串口芯片,突然批量出现“串口偶发失灵”的反馈。具体表现是:设备开着一会,串口助手偶尔收不到数据,但电脑设备管理器里 USB 设备还在,也没有报错。

按换机排除的顺序走:

  1. 换 USB 线——无效
  2. 换 USB 口——无效
  3. 换调试电脑——问题消失

到这里,初步锁定是原来的调试电脑有问题。但如果排查停在这里,下次换一台电脑可能还会犯。所以我们继续追问:为什么这台电脑有问题?用 USB 电流表一测,发现前置 USB 口供电电压只有 4.5V,而 CH340 在 4.5V 下虽然能完成枚举,但某些批次芯片在电流波动时会偶发进入异常状态。把线插到后置 USB 口,电压恢复 5V,问题彻底消失。

这个案例说明一件事:换机排除的终点不是“换一台就好了”,而是**“为什么这一台不行”**。如果只停在第一步,问题会被当成“电脑玄学”丢在一边,下次换个场景还会踩坑。

2.4 串口假故障的高频根源清单

根据多年经验,串口类偶发问题最常见的根源按出现频率大致排序如下:

  1. 供电不稳——USB 口带不动、电源纹波大、电池电压跌落,这类问题最容易伪装成“设备坏”
  2. 线材接触不良——USB 延长线芯线太细、排线端子氧化、杜邦线内部虚断
  3. 电平不匹配——3.3V 对 5V、TTL 对 RS232,有的模块靠三极管搭电平转换,温度一变阈值就漂
  4. DMA 与中断竞争——MCU 上串口 DMA 和中断处理同时踩同一块缓冲区导致数据错乱,这类问题不是硬件坏,是代码和硬件配合的问题
  5. 驱动版本冲突——CH340 老驱动和系统更新“打架”,设备管理器看起来一切正常,实际收发偶发丢包

换机排除法能帮你定位到具体环节,然后对着这份清单去查,效率会高很多。注意一点:换机排除只能告诉你“哪个环节有问题”,不能告诉你“为什么有问题”。定位到环节之后,还需要用示波器、万用表或逻辑分析仪去进一步确认根因,不要偷懒。

3. 蓝牙断开的录屏取证:把“偶发”变成“可回放”

3.1 为什么蓝牙问题总是“一查就好”

蓝牙设备的偶发断开,大概是这三个场景里最气人的一个。它符合一个魔咒:**客户报障时说得绘声绘色,工程师赶到现场一试,一切正常。**而且蓝牙断开后往往会自动重连,等你想抓 HCI 日志时,连接已经恢复,现场早就没了。

所以蓝牙偶发问题排查的第一要务,不是查代码,不是换模块,而是拿到一份可回放的证据。录屏就是这个场景下成本最低、说服力最强的取证手段。

3.2 录屏取证的正确姿势:两层都要录

这里说的“录屏”,不是简单拿手机对着屏幕拍视频,而是分两层。

**第一层:行为录屏。**用系统自带的录屏功能,把整个操作过程录下来。这一层解决的是“用户到底做了什么操作”的问题。很多蓝牙断开根本不是模块问题,而是用户侧行为触发的:

  • 手机锁屏后系统杀掉了蓝牙进程
  • 用户同时开了多个蓝牙设备抢占连接
  • 某个 App 在后台频繁发起蓝牙扫描

这些行为用户自己都没意识到,但录屏回放时一目了然。

**第二层:状态录屏。**把蓝牙的实时状态也录进去。Android 手机在开发者选项里打开“Bluetooth HCI Snoop Log”,系统会把蓝牙的 HCI 包全部记录下来。配合屏幕录制,相当于给蓝牙通信装了一个“行车记录仪”。Windows 端可以在事件查看器里开启蓝牙相关日志,也可以接一个蓝牙嗅探器配合 Wireshark 抓包,但后者门槛偏高,建议先从系统日志入手。

以 Android 端常见场景为例,具体操作步骤是:

  1. 进入设置 → 开发者选项 → 打开“蓝牙 HCI 信息收集日志”
  2. 开启系统自带的屏幕录制功能
  3. 确保手机状态栏能看到当前时间,方便后续和 HCI 日志对时间轴
  4. 正常使用设备,直到故障复现
  5. 结束后导出/sdcard/btsnoop_hci.log,用 Wireshark 打开分析

拿到 btsnoop 日志后,直接看断开那一刻的 HCI 事件:是对方主动断开(Disconnect Complete)、链路超时(Link Supervision Timeout)、还是连接参数更新失败,原因码清清楚楚。这一步基本能把七八成的蓝牙偶发问题定死。

3.3 一个 HC05 与 ESP32 的断开排查实例

说个实际案例。有个用 HC05 蓝牙模块做数据透传的小项目,模块和设备端连接后,正常传输半小时左右必然断开一次,重连后又能继续传输。用户反馈“模块有问题”,测试组也复现了,但一直找不到规律。

我们让测试人员按上面的方法录屏 + 抓 btsnoop,结果发现一个有意思的规律:断开发生的时刻,手机上正好有一条系统通知弹出来,用户点开通知栏的瞬间,蓝牙断开。

后续追查发现:这个品牌手机的 ROM 在通知栏弹出时会触发一次系统级蓝牙扫描广播,HC05 作为从机收到扫描请求后,因为模块固件版本太老,状态机处理异常,直接掉线。换一个固件版本较新的 HC05 模块,问题消失。

这个案例的关键在于:如果不录屏,你永远无法把“通知弹出”和“蓝牙断开”这两个时间点关联起来。用户不会主动告诉你“我刚才看了一眼通知栏”——这个动作在他自己眼里毫无关联。录屏的价值就是给你一条完整的时间线,剩下的事就是找时间线上的“巧合”。

3.4 录屏分析的三板斧

拿到录屏和日志之后,怎么高效分析?我的习惯做法是三点:

  1. 先定零点——把录屏里故障发生的准确时间点标记出来,也就是蓝牙断开的那一刻
  2. 倒推 30 秒——看故障前 30 秒内发生了什么:有没有应用切换、有没有按键操作、有没有电量低提示、有没有系统通知弹出
  3. 对照日志——把系统日志、HCI 日志和录屏时间轴对齐,看断开事件的直接原因代码是什么

最重要的是第 2 步。蓝牙偶发问题里,“断开前的 30 秒”往往藏着真正的触发条件。单独看日志容易错过,单独看录屏又没有技术依据,两者时间轴对齐之后,很多问题一眼就能看穿。时间戳对齐这件事最容易忽略,建议在录屏开始前先录几秒手机设置页,把系统时间拍进去,后面对时间轴会省很多力气。

4. “新旧批次对照”的烧录排查:用 A/B 实验对抗批次玄学

4.1 烧录失败的“批次玄学”是怎么来的

最后一个场景,也是量产阶段最头疼的:**烧录偶发失败,而且只发生在某个批次的板子上。**同一套固件、同一个烧录器,旧批次板子一烧一个准,新批次板子十个里有两三个报错,报错信息还不一样——Keil5 的 Download 弹窗、J-Link 的 timeout、烧录工具刷一半卡死,五花八门。

制造端的第一反应是“这批板子有问题”,研发端的第一反应是“烧录工具配置有问题”。双方互不相让,然后开始踢球。

“新旧批次对照”的核心思路,就是把“批次”当成一个自变量,通过可控实验验证它到底是不是真正的原因,以及差异具体出在哪个环节。这个思路不神秘,就是中学实验课上的控制变量法,但真正做对的人不多。

4.2 对照实验的四步法

第一步:**确认批次差异存在。**不要急着下结论,先把新旧批次各取 10 块板子,每块各烧录一次,记录成功率。如果新旧批次的成功率没有统计差异,那“批次”这个变量可以直接划掉,去查烧录环境和流程。

第二步:**交换固件对照。**把旧批次固件烧到新批次板子上,把新批次固件烧到旧批次板子上。如果问题跟着固件走,说明是固件对芯片版本的兼容性问题;如果问题跟着板子走,说明是硬件差异。

第三步:**交换工具对照。**换一个 J-Link、换一根 SWD 排线、换一台烧录电脑、换一个烧录软件版本。这一步排除烧录环境本身的偶发因素。很多批次问题的真相其实是“新批次板子对烧录环境的容错能力下降了”,旧板子随便怎么烧都行,新板子对环境更敏感。

第四步:**降级配置对照。**把烧录速度降下来、把供电方式从目标板自供电改成烧录器供电、把烧录协议版本调低,看问题是否消失。如果降速后问题消失,大概率是信号完整性或时序裕量问题。

4.3 一个 GD32 J-Link 烧录超时的排查实例

去年某项目,GD32F470 新批次板子,J-Link 烧录偶发报错,有时是 “Failed to load flash loader”,有时是超时。旧批次板子完全正常。按四步法走了一遍:

第一步,新批次 10 块板子烧录 10 次,失败 3 次;旧批次 10 块烧录 10 次,全部成功。批次差异确认存在。

第二步,交换固件:把旧固件烧到新板子,照样偶发失败。说明问题不在固件版本。

第三步,交换工具:换上同事的 J-Link、换线、换电脑,问题依旧。工具因素排除。

第四步,把 J-Link 的烧录速度从 5MHz 降到 1MHz,连续烧录 20 次全部成功。再把速度调回 5MHz,问题复现。进一步用示波器量 SWD 波形,发现新批次 PCB 的 SWD 走线比旧批次长了近 4 厘米,信号边沿变缓,高速烧录时偶发时序违例。

这个案例最大的启示是:**批次差异是客观存在的,但差异可能不在芯片上,而是 PCB 走线、物料供应商、焊接工艺这些“看起来无关”的环节。**对照实验的每一步都在帮你缩小范围,而不是直接跳到“板子坏了”的结论。

4.4 批次差异背后的真正原因清单

根据经验,批次相关烧录失败的高频原因通常如下:

差异来源表现排查方法
芯片版本(Silicon Revision)烧录算法不兼容、握手失败核对芯片丝印、库函数版本
Flash 时序参数差异擦除/写入偶发超时降速烧录对照测试
晶体 / RC 振荡器偏差烧录握手波特率偏移换烧录协议、软件版本
PCB 走线变化高速信号完整性下降降速、换线、量波形
焊接 / 物料差异供电跌落导致烧录中途失败万用表/示波器测供电点电压
Option Bytes / 读保护状态烧录前握手异常、校验失败全片擦除、解除保护对照

每一次对照实验都应该记录成一张表,填清楚:日期、板子批次、固件版本、烧录器型号、烧录速度、结果。这张表最后就是你跟制造、采购部门沟通的硬通货,比任何口头解释都管用。

4.5 Keil5 场景里的“新旧批次对照”变体

有人可能说,我用的就是 Keil5,没有条件做那么复杂的对照。其实变体做法很简单:Keil5 烧录失败最常见的隐藏变量有两个,一个是 Flash 下载算法(Flash Download Algorithm)选错或版本太旧,另一个是烧录时钟频率设置过高。

遇到“新批次板子偶发烧录失败”,先打开 Keil5 的 Utilities → Settings,把烧录时钟频率往低了调,比如从 10MHz 调到 1MHz,再烧一次。如果问题消失,方向就清楚了。然后换回旧批次板子,在同样的高频设置下烧录,如果旧板子正常,那就坐实了是新批次板子对信号完整性的要求更高。这个操作不需要任何额外硬件,五分钟就能完成,但很多人第一反应是去检查芯片型号和焊接,反而绕了远路。

5. 沉淀下来的排查习惯:工具、记录与心态

5.1 排查记录表:一天的无用功怎么变成三天后的线索

排查偶发问题,很多团队靠的是“人肉记忆”——谁记得昨天谁动了什么设置,谁记得上次是换了什么才好的。这种模式在问题简单时没问题,一旦问题拖过三天,记忆就开始不可靠了。

我的做法是维护一份极简的排查记录表,不用什么专业工具,一个表格文件就够了:

时间现象环境信息改了什么变量结果
10:00串口偶发丢数据电脑A,USB延长线,CH340无复现一次
10:15同上同上换USB口未复现
10:30同上同上换USB线正常

每一行就是一个实验。这个习惯救过我很多次——查了两天没结果,回头翻记录表,发现第一天某个不起眼的操作其实已经提供了答案,只是当时没意识到它跟后来某个现象之间的关联。

5.2 录屏是默认手段,不是最后手段

现在的系统录屏成本几乎为零,但要养成“问题一出现就先录屏”的习惯并不容易。很多工程师觉得录屏是给用户用的,自己调试时不需要。但蓝牙这类“状态型”问题,工程师自己录屏同样重要——因为你自己也会漏操作、漏感知。

我的原则是:凡是跟无线通信、连接状态、用户交互相关的偶发问题,录屏从第一天就开始,而不是等到第三次复现才开始。原因很简单:你不知道哪一次复现是“最后一次”,也不知道下一次复现会不会带着更关键的信息。

5.3 给硬件做标记:给自己留一条后路

最后一个技巧,是我个人最推崇的笨办法:**给每一块板子、每一条线材、每一个工具做标记。**用标签机打上编号和批次,旧板子贴“旧批次 2023-XX”,新板子贴“新批次 2024-XX”。这看起来麻烦,但它在“新旧批次对照”类问题排查时的效率提升是几何级的。

你不需要靠猜来判断哪块板子是哪个批次,看一眼标签就有答案。你能清楚地告诉同事“这块是旧批次,那块是新批次”,而不是“好像是这批的,又好像是那批的”。排查偶发问题最怕的就是模糊,标签能帮你把模糊变成确定。

5.4 心态:偶发 bug 靠耐心,不靠聪明

写到最后想聊聊心态。偶发 bug 很少是靠灵光一闪解决的,更多是靠一步步把证据收齐,把变量一个个排除。你不需要在第一时间猜中原因,你只需要保证每一步操作都符合“一次只动一个变量”的原则,让每次实验都有明确结论。大多数偶发问题最后查出来的根因都简单得让人想笑——但它就是藏在一堆没被记录的细节里,藏在一次“顺手”的操作里,藏在一块没贴标签的板子里。

串口假故障、蓝牙随机断开、烧录批次玄学,这三个问题看起来毫无关联,本质上却是同一件事:**把不可复现的问题,变成可回放的证据;把所有猜测,变成可验证的实验。**这套方法叠加上耐心,遇到偶发 bug 时就能少一点焦头烂额,多一点从容。希望这篇东西能在你下次面对“它刚才还是好好的”这句话时,帮你省下几个不眠之夜。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询