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

pySerial写入指令后readline返回写入内容,无法获取正确串口数据

pySerial串口通信readline返回发送指令的问题排查与解决

问题概述

使用pySerial进行串口通信时,readline()无法获取设备返回的正确数据,多数情况下读取到的是自身发送的指令(#001STA或001STA),仅偶尔出现异常结果。预期设备返回格式为:

#001,▒▒▒,25080,009,009,004,004,000,66,00700,069,042,0000000000000000000000000

代码问题分析

第一段代码存在的问题

  1. 端口配置错误:定义了rereport = "COM16"但未赋值给ser.port,导致串口未正确指定通信端口。
  2. 流控设置矛盾:代码中ser.xonxoff = True开启了软件流控,但注释标注为“disable”,若设备采用无流控配置,会导致通信不匹配。
  3. 指令格式可能缺失结束符:发送的指令#001STA未添加设备要求的换行符(如\r\n),设备可能无法识别指令并返回数据。

第二段代码存在的问题

  1. 串口未打开:仅配置了端口参数,未调用ser.open()就尝试发送数据,会直接抛出异常。
  2. 发送数据写法错误:ser.write(wrData).encode("Ascii")逻辑错误,正确写法应为ser.write(wrData.encode("Ascii")),当前写法会导致发送原始字符串而非字节数据,引发通信异常。
  3. 无缓冲区初始化:未清空输入缓冲区,残留的历史数据会干扰读取结果。

解决建议

1. 修正串口初始化与配置

  • 确保端口参数正确赋值:将第一段代码的rereport = "COM16"改为ser.port = "COM16"。
  • 串口打开前添加异常捕获,避免因端口占用等问题崩溃:
    try:
        ser.open()
    except serial.SerialException as e:
        print(f"串口打开失败: {e}")
        exit()
    
  • 统一流控设置:根据设备手册确认流控模式,若为无流控,设置:
    ser.xonxoff = False
    ser.rtscts = False
    ser.dsrdtr = False
    

2. 修正发送数据逻辑

  • 发送数据前必须将字符串转为字节对象,第二段代码中修正为:
    ser.write(wrData.encode("ASCII"))
    
  • 给指令添加设备要求的结束符(多数串口设备需要\r或\r\n作为指令结束标志):
    wdata = "#001STA\r\n"
    

3. 规范缓冲区与读取逻辑

  • 串口打开后清空一次缓冲区即可:
    ser.flushInput()
    ser.flushOutput()
    
  • 读取数据前先检查输入缓冲区是否有数据,避免空读或超时读取残留数据:
    ser.write(wdata.encode())
    time.sleep(0.3)  # 等待设备响应,时长根据设备调整
    while ser.in_waiting > 0:
        response = ser.readline().decode().strip()
        # 跳过设备回显的指令(若设备存在回显)
        if response == wdata.strip():
            continue
        print(f"设备返回: {response}")
    

4. 排查硬件与设备回显

  • 检查串口接线是否正确,避免TX/RX短接导致的回环读取。
  • 使用串口助手测试:发送指令后观察是否有回显,若设备默认回显发送的指令,读取时需跳过回显内容,再处理真正的返回数据。

修正后的示例代码

import time
import serial

# 串口配置
ser = serial.Serial()
ser.port = "COM16"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
ser.timeout = 1
ser.write_timeout = 0.5
# 匹配设备流控(此处为无流控)
ser.xonxoff = False
ser.rtscts = False
ser.dsrdtr = False

try:
    ser.open()
except serial.SerialException as e:
    print(f"串口打开失败: {e}")
    exit()

# 初始化缓冲区
ser.flushInput()
ser.flushOutput()

# 带结束符的指令
wdata = "#001STA\r\n"
print("通信开始")

try:
    while ser.is_open:
        # 发送指令
        ser.write(wdata.encode())
        # 等待设备响应
        time.sleep(0.3)
        # 读取所有可用返回数据
        while ser.in_waiting > 0:
            response = ser.readline().decode().strip()
            # 跳过回显的指令
            if response == wdata.strip():
                continue
            print(f"设备返回: {response}")
        # 间隔1秒再次发送
        time.sleep(1)
except KeyboardInterrupt:
    print("程序终止")
finally:
    ser.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:02:19