Linux串口接收0x0D莫名转换为0x0A问题的根本原因分析

本文内容参考:

Linux串口接收字符莫名转换问题_linux 串口接收 将0x0d转换为0x0a-CSDN博客

特此致谢!

目录

一、问题现象

二、问题分析

[1. 排查问题](#1. 排查问题)

[2. 具体分析](#2. 具体分析)

三、问题解决

[1. 代码修改](#1. 代码修改)

[2. 运行结果](#2. 运行结果)


一、问题现象

笔者最近在实际项目调试时,发现了一个比较奇怪的现象。下位机(MCU)明明发送的数据是对的,上位机却总是不能校验通过,从而导致帧被丢弃。经过检查,大多数情况下是没问题的,但是当有0x55 0xAA 0x00 0x0D ......的时候,上位机(SoC)收到的却总是0x55 0xAA 0x00 0x0A ......,从而导致接收的帧校验总是不能通过。

二、问题分析

1. 排查问题

一开始笔者认为是下位机回复的本身就有问题,本身回复的就是0x0A。结果笔者在下位机代码中写死发送0x0D,经过检查,上位机Soc侧实际收到的确实就是0x0A。这就排除了下位机(MCU)代码的问题,将问题锁定在了上位机(SoC)本身、尤其是Linux串口自身机制上。

2. 具体分析

既然明确了是Linux串口自身的问题,而这个问题又是笔者之前从未遇到过的,那么最直接快捷的方法就是在百度上(现在也可以在豆包上)搜索,看看是否有前人遇到过此问题,又是怎样解决的。经过搜索,其实遇到此问题的人还是比较多的,其中选了一篇讲解得最为清楚的(就是本文开头致谢的那篇博文)。此问题的根本原因是:

串口配置时未禁用输入模式的字符转换标志位,导致系统驱动自动修改了接收数据。

具体来说是,串口的c_iflag(输入模式标志)中,默认可能开启了ICRNL标志(字符转换标志位) ------ 该标志会将接收的CR(0x0D)自动转换为NL(0x0A)。若代码中未明确清除这个标志位,将会导致数据被篡改:

1)发送数据包含0x0D → 串口驱动检测到CR;

2)因ICRNL开启,驱动自动将其替换为NL(0x0A);

3)最终应用层收到的就是0x0A而非原始的0x0D。

三、问题解决

1. 代码修改

既然明确了问题的根因,那么解决起来就比较容易了。在SoC侧Linux串口代码中做以下修改(添加红色矩形框中的一行):

实际上就是清除默认开启的ICRNL标志位。

2. 运行结果

作以上修改之后,再次编译、烧录(替换)、运行上位机可执行程序后,工作正常,问题解决。

相关推荐
拂拉氏1 小时前
【知识讲解】 Linux之动静态库的了解
linux·运维·服务器·动静态库
Fcy6482 小时前
Linux下 五种IO模型的认识与⾮阻塞IO的实现
linux·服务器·io
Mikko72 小时前
Linux 重启后日志没了?进程被 OOM 杀了去哪看?logrotate 之后日志还往旧文件写?三台真机实测日志与性能排查
linux·运维·centos
书生执笔画浮沉2 小时前
分享一个开源小工具CAdapt
linux·c·gnu·glibc·kernel·升级·灵感
mounter6253 小时前
Linux 内核热升级(Live Update)技术详解:PCI、VFIO 与 IOMMU 子系统的演进与实战解析引言
linux·linux kernel·kernel·iommu·vfio
砚凝霜3 小时前
【软考信息安全】第十九章 Unix/Linux安全分析与防护
linux·安全·unix
creator_Li4 小时前
Linux 的 Page Cache
linux·page cache
KING-WU5125 小时前
Linux GDB 调试实战指南:从编译到断点调试
linux·运维·服务器
Lucis__5 小时前
深入理解程序链接与加载—从动静态链接到库加载
linux·elf·链接·程序·动静态库
影视飓风TIM6 小时前
Linux 进程信号原理与剖析
linux·运维·服务器