Python读取串口持续发送数据解析:起始字节校准及Struct用法咨询
解决串口帧同步与数据解析问题
首先,你遇到的核心问题是串口流式数据的帧同步——因为串口本身没有包边界,启动读取时很可能抓到半帧数据,导致起始字节不符合要求。结合你的需求,我们先搞定帧同步,再用struct模块来高效解析数据。
一、先实现帧同步:对齐到0x98开头的完整帧
你的目标帧以连续两个0x98作为起始标记,所以我们需要先跳过无效字节,直到找到这个帧头,再读取剩余的字节组成完整的13字节帧。修改后的代码如下:
import serial port = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1) def find_valid_frame(port): # 寻找连续两个0x98作为帧头,之后读取剩余11字节组成完整帧 prev_byte = None while True: byte = port.read(1) if not byte: continue # 超时则继续等待数据 current_byte = ord(byte) # 检测到连续两个0x98,返回完整13字节帧 if prev_byte == 0x98 and current_byte == 0x98: return byte + port.read(11) prev_byte = current_byte while True: valid_frame = find_valid_frame(port) print(f"有效帧: {valid_frame}") # 后续在这里添加解析逻辑
这个逻辑的优势是:不管启动时读到多少无效字节,都会一直等待直到找到符合要求的帧头,确保每次处理的都是完整、起始正确的13字节帧。
二、用struct模块解析帧数据
struct模块的作用是把字节串转换成Python的基本数据类型(比如整数、浮点数等),非常适合处理固定格式的串口帧。
假设你的13字节帧结构是:
- 字节0-1:帧头(0x98, 0x98)
- 字节2-12:数据段(你需要提取的是索引为4的字节,也就是帧中的第5个字节)
我们可以用struct.unpack来快速提取目标字节:
import struct def parse_frame(frame): # 格式字符串'13B'表示将13字节解析为13个无符号字节(0-255) all_bytes = struct.unpack('13B', frame) target_byte = all_bytes[4] # 对应你要的Byte[4] print(f"提取到的Byte[4]值: 0x{target_byte:02X}") return target_byte # 在之前的循环中调用解析函数 while True: valid_frame = find_valid_frame(port) print(f"有效帧: {valid_frame}") parse_frame(valid_frame)
关于struct格式字符串的小说明:
B:代表一个无符号字节(unsigned char),范围0-255- 如果你需要解析其他类型的数据(比如16位整数),可以用
H(无符号短整型)、h(有符号短整型)等格式,比如2B H 8B表示前两个字节是单个字节,接下来两个字节是16位无符号整数,最后8个是单个字节。
额外优化建议
- 给串口添加
timeout参数(比如timeout=1),避免程序一直卡死在read()操作上 - 如果控制盒的帧带有校验位(比如CRC、和校验),建议加上校验逻辑,进一步确保帧的完整性
内容的提问来源于stack exchange,提问作者user9204389




