linux串口对0X0D、0X0A等特殊字符的处理

目录

BUG场景:

问题描述

原因分析:

解决方案:

BUG场景:

最近项目有用到STM32和RK3588进行串口通信传输温湿度的数据,然后遇到了CRC8校验失败的BUG


问题描述

如上图所示,在通信的过程中出现了CRC校验失败的问题,一开始以为是偶现的BUG,因为有时候运行1个小时才会出现,有时候运行5分钟就出现了,但是排查多几次发现每次CRC校验的那一帧数据都是一样的,CRC错误也是固定的那个值会校验失败,于是就在STM端打印发送的数据,发现发出的数据是55 15 02 12 0D A1 AA,其中A1是CRC校验值,但是linux端收到却是

55 15 02 12 0A B4 AA,B4是CRC校验值


原因分析:

后来发现串口发送字符是有特殊字符的,例如下面这个表格的都是特殊字符:

字符名 缩写 ASCII 码 含义 & 典型用途
空字符 NUL 0x00 1. 数据填充(如固定长度数据包补位);2. 部分协议的 "数据包结束标记";3. 初始化串口缓冲区
标题开始 SOH 0x01 自定义协议中标记 "数据包头部 / 指令类型段" 开始(如区分数据帧和指令帧)
文本开始 STX 0x02 标记 "有效数据正文" 开始(与 ETX 配对,界定数据体范围)
文本结束 ETX 0x03 标记 "有效数据正文" 结束(与 STX 配对,最常用的串口帧分界符之一)
传输结束 EOT 0x04 标记 "整个传输会话结束"(如一次批量数据传输完成后发送)
询问 ENQ 0x05 向接收方发起 "状态查询"(如:询问对方是否就绪、是否收到数据)
确认 ACK 0x06 接收方向发送方反馈 "数据正确接收"(最常用的确认字符)
响铃 BEL 0x07 触发设备蜂鸣(调试场景,如传输出错时提醒)
回车 CR 0x0D 1. 换行控制(Windows 系串口换行:CR+LF=0x0D+0x0A);2. 多数串口协议的 "帧结束符"(如 Modbus ASCII、AT 指令)
换行 LF 0x0A 1. 换行控制(UNIX 系串口换行仅用 LF);2. 配合 CR 作为帧分隔符
数据链路转义 DLE 0x10 协议 "转义符":标记后续字符为 "普通数据"(避免特殊字符被误判为控制符,如传输 0x02 时先送 DLE+0x02)
设备控制 1(XON) DC1/XON 0x11 软件流控核心:接收方发送 XON,通知发送方 "恢复数据传输"(解决缓冲区溢出)
设备控制 3(XOFF) DC3/XOFF 0x13 软件流控核心:接收方发送 XOFF,通知发送方 "暂停数据传输"
否定确认 NAK 0x15 接收方向发送方反馈 "数据错误 / 未收到"(要求重传)
同步空闲 SYN 0x16 同步串口(如 RS-485 同步模式)的 "同步字符",用于对齐收发时钟
转义 ESC 0x1B 切换命令模式(如 AT 指令中 ESC 退出当前模式、自定义协议中切换指令集)
记录分隔 RS 0x1E 多组数据的分隔符(如批量传输多条记录时,分隔不同行数据)
字符 ASCII 码 典型用途
空格 0x20 字段分隔(如调试输出时分隔参数:temp: 25 hum: 60)
:(冒号) 0x3A 1. Modbus ASCII 帧的地址 / 功能码分隔;2. 自定义协议的键值分隔(如addr:10)
=(等号) 0x3D AT 指令 / 自定义协议的参数赋值(如BAUD=9600)
,(逗号) 0x2C 多参数分隔(如x:100,y:200,z:300)
*(星号) 0x2A 校验和分隔(如 Modbus ASCII 帧::010300000001840A\r\n 中 * 分隔数据和校验和)
?(问号) 0x3F AT 指令查询(如AT+CSQ? 查询信号强度)

这些特殊字符在linux端收到会自动转换成其它的字符,而温湿度值又不是每次都是固定值,所以才会造成是CRC校验失败偶现BUG的现象,实际上它是必现的BUG

解决方案:

解决的办法就是在linux的串口初始化函数里面加一句限制,清除串口输入阶段的一系列自动处理 / 控制行为,让输入数据以 "原始、无修改" 的方式被读取,就是下面这段代码了

复制代码
    struct termios options;
    options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP

        | INLCR | IGNCR | ICRNL | IXON

        | IXOFF | IUCLC | IXANY | IMAXBEL);

配置之后,linux串口读取的数据就是原始的数据了,不会再被篡改了,下面就是接收到的原始数据,可以看到已经能够正常接收0X0D、0X0A这种特殊字符的数据了

总结:

项目中使用STM32与RK3588串口通信传输温湿度数据时,出现CRC8校验失败问题。经排查发现,Linux端会将特殊字符(如0x0D、0x0A等)自动转换,导致接收数据被篡改,CRC校验值错误。解决方案是在Linux串口初始化时清除输入阶段的自动处理标志(IGNBRK、ICRNL等),使数据以原始形式接收。修改后,系统能正确接收特殊字符,CRC校验恢复正常。该问题表面偶现实为必现,关键在于禁用串口的自动转换功能。

相关推荐
且从容.4 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道5 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
Zw-awa5 小时前
OLED为什么能显示字:软件I2C换成硬件I2C
stm32
不脱发的程序猿6 小时前
GD32串口数据收进内存之后DMA如何处理?
单片机·嵌入式硬件·dma·嵌入式·串口通信·gd32
且从容.8 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落9 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨9 小时前
WSL2的安装与使用
linux·wsl
微小的鱼9 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng10 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
Android系统攻城狮10 小时前
Linux FFmpeg深度解析之av_write_frame调用流程与实战(三十三)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频