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校验恢复正常。该问题表面偶现实为必现,关键在于禁用串口的自动转换功能。

相关推荐
学习路上_write2 小时前
AD5293驱动学习
c语言·单片机·嵌入式硬件·学习
影阴2 小时前
存储器和寄存器
stm32·单片机·嵌入式硬件
Better Bench2 小时前
Ubuntu aarch64\arm64系统安装vscode
linux·vscode·ubuntu
暴风游侠3 小时前
linux知识点-服务相关
linux·服务器·笔记
阿海5743 小时前
卸载nginx的shell脚本
linux·nginx
JANG10243 小时前
【Linux】常用指令
linux·服务器·javascript
DeeplyMind3 小时前
使用parted工具扩展QCOW2磁盘大小完整方案
linux·qemu·virtialization
蓝天~白云3 小时前
ESXI虚拟机启动卡住在0%,无法关闭
linux·运维·服务器
明月心9523 小时前
IP 中 0/24 和 0/16 的区别
linux·服务器·网络·ip