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

使用Pyserial发送多条指令时引导后后续指令未被设备接收如何解决

核心问题定位

  1. 串口会话被反复重置:代码在遍历每条指令的循环里,每次都执行了ser.close() + ser.open(),串口每次重开都会断开和设备的现有连接,引导阶段完成后重开串口相当于重新建立连接,之前的引导会话状态直接丢失,设备自然不会响应后续在新会话里发的指令。
  2. 指令缺少结束符:绝大多数串口设备都要求指令末尾携带换行符(\n/\r/\r\n)才会判定为一条完整的可执行指令,Putty默认会在你敲回车的时候自动补全结束符,所以手动操作正常,而原代码里直接发送指令内容,没有额外追加设备要求的结束符,设备会认为指令未结束,一直等待后续输入。
  3. 计时逻辑错误:变量x初始值为0,第一次进入循环时time.perf_counter() - x会直接远大于设置的等待时间,导致指令刚发送就跳出等待逻辑,还没等设备返回就清空了缓冲区。
  4. 写超时配置不合理:初始化串口时设置了write_timeout=0,部分场景下会导致写入操作直接非阻塞返回,实际上数据还没完全写入串口缓冲区就被后续操作打断。

修复后的代码示例

import serial
import time
from datetime import datetime

# 加载指令列表
with open('commands.txt') as f:
    list_of_commands = [tuple(map(str.strip, i.split(','))) for i in f]

# 初始化日志
date = datetime.now().strftime("%Y-%m-%d")
log = open(f'{date}.txt', 'w+', encoding='utf-8')

# 加载串口配置
with open('info.txt', 'r') as f:
    lines = f.readlines()
    port = lines[0].strip()
    baud = int(lines[1].strip())

ser = None
try:
    # 串口仅初始化打开一次
    ser = serial.Serial(
        port=port,
        baudrate=baud,
        timeout=2,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        # 关闭write_timeout=0的配置,使用默认阻塞写入
        write_timeout=5
    )
    # 等待串口初始化完成
    time.sleep(2)

except ConnectionError:
    log.write('串口连接失败')
else:
    for cmd_item in list_of_commands:
        sleep_time = int(cmd_item[0])
        cmd = cmd_item[1]
        # 追加设备要求的结束符,这里如果是CR就改成\r,CRLF就改成\r\n
        encoded_cmd = (cmd + '\n').encode("utf-8")
        # 发送指令
        ser.write(encoded_cmd)
        # 确保数据完全发出
        ser.flush()
        # 等待设备返回
        wait_start = time.perf_counter()
        while time.perf_counter() - wait_start < sleep_time:
            if ser.in_waiting:
                recv_data = ser.readline()
                recv_text = recv_data.decode('utf-8', errors='ignore')
                print(recv_text)
                log.write(recv_text)
                log.flush()
        # 仅清空输入缓冲区,不要清空输出缓冲区避免未发出的数据被丢弃
        ser.reset_input_buffer()
        print(f"完成指令发送: {cmd}")

finally:
    if ser and ser.is_open:
        ser.close()
    log.close()

额外注意事项

  • 先确认设备要求的指令结束符类型,常见的有\n(LF)、\r(CR)、\r\n(CRLF)三种,需要和设备要求保持一致
  • 如果是工业类串口设备,建议额外开启流控配置(如果设备支持的话),或者将发送后等待flush的时间延长到0.1~0.5秒
  • 不要在指令执行过程中随意关闭、重开串口,会直接丢失当前会话的所有状态,导致设备回到初始等待引导的状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 07:27:01