You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyserial读取未遵循指定字节数问题求助

嘿,我之前也遇到过串口读取参数没按预期工作的情况,咱们一步步来排查解决这个问题:

先搞清楚核心问题:为啥读2字节却得到超过16位的值?

大概率是这几个原因导致的,咱们逐个排查:

1. 串口缓冲区残留了旧数据

如果之前的串口会话没清空缓冲区,你调用read(2)时可能会把之前残留的字节和新字节一起读进来,结果自然超过2字节。
解决办法:读取前强制清空输入缓冲区
比如用pySerial的话:

ser.flushInput()  # 读取数据前先清空缓冲区

如果是bash脚本:

stty -F /dev/ttyUSB0 flush

2. 对read命令的参数理解有误

很多串口库的read(n)是「最多读n字节」而非「恰好读n字节」,或者受超时设置影响。比如pySerial如果设置了timeout=0(非阻塞),可能会返回少于2字节,但如果设备一直在连续发数据,而你没处理帧边界,就会读到连续的多字节数据。
解决办法:

  • 确保超时设置正确:如果要阻塞到读够2字节,把timeout设为None(pySerial)
  • 验证读取的字节长度:每次读取后检查返回的字节数是不是2,比如:
ans_bytes = ser.read(2)
if len(ans_bytes) != 2:
    print(f"Warning: Read {len(ans_bytes)} bytes instead of 2")
    # 这里可以加重试逻辑

3. 字节转整数时没处理字节序或截断错误

就算你真的读了2字节,如果转整数时用错了字节序,或者不小心把多个读取结果拼接了,也会得到超过16位的值。
正确的转换方式(以pySerial为例):

# 假设设备发送的是小端无符号16位整数
ans = int.from_bytes(ans_bytes, byteorder='little', signed=False)
# 如果是大端,就改成byteorder='big'

要是你把多次读取的结果存在同一个变量里没重置,比如循环里ans += new_value,那肯定会累积成大数,记得每次读取前重置变量。

4. 串口配置和设备不匹配

波特率、奇偶校验、停止位、数据位这些参数必须和发送设备完全一致,否则会出现字节同步错误,导致读取的字节混乱,看起来像是读多了。
比如pySerial的正确配置示例:

import serial
ser = serial.Serial(
    port='/dev/ttyUSB0',  # 你的串口端口
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=None  # 阻塞直到读够指定字节数
)

5. 设备发送的是带帧头/帧尾的多字节帧

如果设备发送的不是单纯的2字节数据,而是包含帧头、校验位的完整帧,你直接读2字节就会读到帧头+部分数据,或者连续的多帧数据,自然超过16位。
解决办法:先用串口调试工具(比如minicom、串口助手)监听设备发送的原始数据,确认帧格式,比如是不是0xAA + 2字节数据 + 0xBB这种格式,然后先读取帧头,再读取2字节有效数据。

最后验证的小技巧

读取到字节后,先打印原始字节的十六进制值,而不是直接转成整数,这样能直观看到是不是真的读了2字节:

print(f"Raw bytes: {ans_bytes.hex()}")

如果输出是4个十六进制字符(比如1234),那就是2字节,转成整数就是16位;如果是更多字符,那就是读多了,回到前面的步骤排查。

内容的提问来源于stack exchange,提问作者Raizen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:05:18