串口日志乱码:设备在说话但你读不懂它

2026-08-31

串口日志乱码里最容易被误诊的一点是:它未必是串口的问题。日志是一串字节,字节怎么变成字,是上层的编码约定说了算。所以第一步不是改波特率,而是把接收窗口切到 HEX 模式——链路对不对,一眼就分出来了,之后才轮到分型。

先分清:你在看的是日志,不是应答

控制类的串口问题有一个天然的便利:你发一条命令,它回一串东西,一来一回可以反复试。日志不是这样。设备的调试口是单向输出的,上电就开始吐,你发什么它多半都不理。这带来两个直接后果,决定了整个排查方式和《RS232 串口乱码?6 步定位波特率与接线问题》那种指令排查不一样:

  • 发送端的参数你改不了。日志的波特率、数据格式是设备固件写死的,你只能调自己这一端去凑它。所以”两端设成一致”这句话在这里只剩一半——另一半是常量。
  • 你没有已知正确的参照物。指令排查里你至少知道自己发了什么,能拿收到的和发出的比。看日志时你手上什么都没有,只有一串来路不明的字节。

第二条是真正的难点。下面这套流程的目的,就是先给自己造一个已知正确的参照物出来。

第一刀:切到 HEX 模式,用换行符给链路定性

串口调试助手把同一串字节按两种方式显示:ASCII 模式把字节当字符解释,HEX 模式直接把字节值打出来,不做任何解码。这个差别就是我们要的参照物。

切到 HEX 之后,去找 0D 0A 这一对。ASCII 规范里 0x0D 是回车、0x0A 是换行,任何按行输出的文本日志都会规律地出现行结束符(有的设备只发 0x0A)。它是整条流里你唯一能事先断定”一定存在、且值一定是这个”的东西。

由此得到一条判据:

  • HEX 里能看到规律出现的 0D 0A,且它们的间隔大致对应日志行的长度——说明字节被完整、正确地收下来了。串口的帧参数是对的,问题在字节之上,也就是编码或显示层。这时候再去改波特率,只会把本来对的参数改坏。
  • HEX 里根本找不到 0D 0A,字节值杂乱无章——说明字节本身就收错了。这才是波特率、数据位、校验位、停止位或电平的问题,按既有那篇的顺序走就行,本文不重复。

顺带一个容易忽略的现象:波特率不匹配时收到的字节看着”随机”,但常常会反复出现同样的几个值。原因在帧结构——异步串口每一帧都由起始位的下降沿重新同步,采样点在帧内的偏移是固定的,所以同一个源字节每次被采错成的结果也是同一个。乱得有重复规律,指向速率不匹配;乱得完全不重样,更像是线路上的干扰。

只有中文成方块、英文数字全对:这是编码,不是串口

这是日志乱码里最独特的一型,也是指令排查那套完全覆盖不到的。现象很好认:时间戳、模块名、ERROR0x 开头的十六进制值都清清楚楚,一到中文提示就成了方块、问号或者一串希腊字母。

它不可能是串口参数错。串口是按字节搬运的,参数错了不会挑着字符错——ASCII 字符和汉字在链路上没有任何区别。能挑着错,说明字节是好的,是解码规则不对:设备按一种字符编码把汉字拆成字节发出来,你的终端按另一种规则把字节拼回字。拼不回去,就显示成替代符号。

判断方向也就跟着确定了:不要碰串口设置,去改接收端的编码;或者如果设备侧的日志格式可配,让它输出纯 ASCII。如果现场是多方设备混装、日志里中英文都有,把接收工具的编码固定成设备侧那一种,比逐台去猜省事。

从字节形态认编码:UTF-8 与 GBK 的辨认方法

不知道设备用哪种编码时,HEX 模式能直接看出来。这两种编码对汉字的字节形态是规范定死的,不随设备型号变:

  • UTF-8 把常用汉字编成 3 个字节:首字节的高位是 1110,落在 E0EF 区间;后面两个续字节高位是 10,落在 80BF 区间。所以 HEX 里看到 E4 B8 AD 这种”一个 E 打头 + 两个 8/9/A/B 打头”的三连组,基本可以断定是 UTF-8。
  • GBK 把汉字编成 2 个字节:首字节落在 81FE,第二字节落在 40FE(不含 7F)。特征是两两成对,且第二字节经常落在 ASCII 可见字符的范围里。

这条判据的实际价值在于反向确认:如果你的终端设成 UTF-8,而 HEX 里汉字明显是两字节成对的,那么按 UTF-8 解码时这两个字节大概率对不上 UTF-8 的三字节结构——注意 GBK 与 UTF-8 的字节范围有重叠,所以结果可能是被判为非法序列换成替代符,也可能被解成别的汉字,两种表现都指向同一个原因。这就解释了”英文正常、中文成方块或成怪字”的现象,不用再怀疑线和参数。

开头一段乱、之后一路正常

另一种有明确形态的分型:每次给设备断电重上电,日志最开头都是一段读不懂的东西,长度还差不多,过了那一段之后就全都正常。

这种”位置固定在流的开头、长度大致稳定”的乱码,指向的是设备在启动过程中换过串口速率——有的固件在引导阶段与应用阶段用两套串口参数,两段用的不是同一个速率,你这边只能对上其中一段。另一种可能是上电瞬间线路电平尚未稳定,接收端把噪声当成了起始位。

区分办法很简单:不断电、只把接收端重新打开一次。如果重新打开后收到的是干净的日志,说明那段乱码只在上电时产生,属于启动阶段现象;如果一打开就乱,那和上电无关。

要不要处理它,取决于你关心的是哪一段。只看应用日志的话,忽略开头那段是最省事的;必须看引导阶段输出的话,就得按引导阶段那套参数另开一个会话去收。

字都认得、句子却断了:这是丢,不是乱

有一类被叫做”乱码”的现象其实完全不是乱码:每个字都认得,但行是残的——一句话说到一半没了,下一行从中间开始。

判据一句话就够:**字不认得是错,字认得而内容缺是丢。**两者的成因不重叠。

丢的方向要查的是接收侧的吞吐:日志是持续不断的流,不像指令那样一问一答有间隙,接收端缓冲区被填满、上位机窗口刷新跟不上、或者中间有环节做了缓存和分包,都会造成整段消失。链路上的字节其实是对的,只是没被完整交到你眼前。

所以看到断行别去动波特率——设备端的速率你本来就改不了,能动的只有接收端,而降接收端速率只会让解码全错。要做的是减少接收端的负担:关掉时间戳和自动滚屏这类附加处理,或者直接存文件再离线看。

日志里混着二进制:ASCII 模式把协议帧显示成了怪符号

有些设备的调试口不只吐文本,还会把收发的协议帧原样打出来。这些字节本来就不是可见字符,在 ASCII 模式下自然显示成怪符号。

它和真乱码的区别在分布规律:怪符号总是出现在同一类日志行的相同位置(比如每次通信记录之后),而不是均匀撒在整条流里。确认方法还是切 HEX——看那些怪符号对应的字节,如果它们构成了你认识的帧结构(固定的帧头、长度字段、校验字节),那就不是故障,是设备在如实输出。

这种情况下真正该做的是别用纯文本模式看日志,换成能同时显示 ASCII 与 HEX 两栏的视图,文本和帧各看各的。

转接环节:USB 转串口与串口服务器

如果中间还经过一层转换——USB 转串口芯片,或者把串口引到网络上的串口服务器——USB 转串口芯片,或者把串口引到网络上的串口服务器。它们各自会引入不同的表现。

USB 转串口这一层,字节内容一般不会被改写,但驱动侧对参数的支持范围是有边界的——某些非标准速率驱动不一定支持,设成了也未必真按那个速率跑。判断方法不变:HEX 里找 0D 0A,找不到就说明这一层没把速率落实。

串口服务器这一层多一个变量:它要把连续的串口字节流切成网络包,切的位置由它的打包策略决定。这会改变你看到的断行位置,但不改变字节内容本身。所以经过串口服务器之后出现的”断行奇怪”未必是故障,而字节值出错就一定不是打包策略能解释的。选型与参数配置可参考《串口服务器(串口转网口)选型科普》。

最容易栽的坑

**一看到乱码就开始一档档试波特率。**指令排查里这么做是对的,因为你有明确的正确回应作为终点。看日志时你没有终点,试到某一档”看起来顺眼了”就停下,很可能只是碰巧把噪声解成了可读字符,反倒把原本正确的参数改坏了。先切 HEX 找行结束符,用二十秒把”字节对不对”这个问题一次性回答掉,比试十遍都值。

第二个坑是把调试口当控制通道用。日志口的输出格式随固件版本改动,没有稳定性承诺,也不响应命令。设备的控制通道是另一套东西,格式和参数由厂商指令文档规定,见《RS232 与 RS485 串口控制速查与实战》。拿日志口的输出去做中控的状态判断,固件一升就全线崩。

下一步:把每台设备的日志口参数(速率、数据格式、字符编码)和控制口分开登记成两行,别混在一栏里。这两个口在同一台设备上用不同参数是很正常的事,登记表混着写,下次接的人一定会拿错。

需要展厅软硬件方案或定制开发?

留言讨论

评论发布后会被人工复核,违规内容将被删除。

    还没有人评论,来说说你的看法

    如果发表没有反应,可以前往联系我们告诉我们。

    这个页面有问题?

    提交时会附带当前页面地址和浏览器信息,帮助我们定位问题。不填联系方式即为匿名。