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

PySerial实现DB9 RS232串口流控请求:XonXoff/RTSCTS/DSRDTR示例

PySerial 串口流控实现指南(适配13字节接收阈值)

嘿,刚好对PySerial的串口流控这块熟得很,来给你详细讲讲XonXoff、RTS/CTS、DSR/DTR这三种方式的用法,完美适配你那“接收超13字节就触发流控”的需求~

先快速给你区分下三者的核心差异:

  • Xon/Xoff(软件流控):纯软件逻辑,靠发送特定控制字符让发送端停/发,不用额外硬件引脚,适合缺硬件流控引脚的场景。
  • RTS/CTS(硬件流控):靠串口的RTS、CTS引脚电平变化来控制,硬件层面实现,可靠性拉满,工业场景常用。
  • DSR/DTR(硬件流控):原本是用来检测设备是否就绪的引脚,偶尔也能当流控用,但不如RTS/CTS普遍,优先级靠后。

1. Xon/Xoff 软件流控(无硬件依赖首选)

这种方式不用折腾硬件引脚,靠发送XOFF(0x13)告诉发送端“别发了”,发送XON(0x11)告诉它“继续发”。PySerial可以自动处理,但如果你要严格卡13字节的阈值,手动控制会更精准。

手动控制示例(精准适配13字节阈值)

import serial
import time

# 初始化串口,记得替换成你的串口号
ser = serial.Serial(
    port='COM3',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_1,
    bytesize=serial.EIGHTBITS,
    xonxoff=False  # 关闭自动控制,手动发XON/XOFF
)

received_data = b''
threshold = 13  # 你的13字节阈值

try:
    while True:
        # 检查有没有待接收的数据
        if ser.in_waiting > 0:
            chunk = ser.read(ser.in_waiting)
            received_data += chunk
            print(f"当前已接收: {len(received_data)} 字节")
            
            # 达到阈值就触发流控
            if len(received_data) >= threshold:
                print("⚠️ 达到13字节阈值,发送XOFF让发送端停止")
                ser.write(b'\x13')  # 发送XOFF控制字符
                # 这里加你的数据处理逻辑,比如解析、存储
                time.sleep(2)  # 模拟处理耗时
                # 处理完恢复接收
                print("✅ 数据处理完成,发送XON让发送端继续")
                ser.write(b'\x11')  # 发送XON控制字符
                received_data = b''  # 清空接收缓冲区
finally:
    # 程序结束记得关闭串口
    ser.close()

如果你不想手动控制,也可以直接开xonxoff=True,PySerial会自动在接收缓冲区快满时发XOFF,但没法精准卡13字节的阈值,看你需求选就行。


2. RTS/CTS 硬件流控(高可靠性首选)

这种是硬件层面的流控,靠DB9串口的第7脚(RTS)和第8脚(CTS)来通信:我们拉低RTS电平,发送端检测到CTS变低就停止发送;拉高RTS,发送端就继续。

手动控制示例(精准卡阈值)

import serial
import time

ser = serial.Serial(
    port='COM3',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_1,
    bytesize=serial.EIGHTBITS,
    rtscts=False  # 关闭自动控制,手动操作RTS
)

received_data = b''
threshold = 13

try:
    ser.setRTS(True)  # 初始状态:允许发送端发送
    while True:
        if ser.in_waiting > 0:
            chunk = ser.read(ser.in_waiting)
            received_data += chunk
            print(f"当前已接收: {len(received_data)} 字节")
            
            if len(received_data) >= threshold:
                print("⚠️ 达到阈值,拉低RTS停止接收")
                ser.setRTS(False)  # 拉低RTS引脚,通知发送端停发
                # 处理数据逻辑
                time.sleep(2)
                print("✅ 处理完成,拉高RTS恢复接收")
                ser.setRTS(True)
                received_data = b''
finally:
    ser.close()

⚠️ 注意:用这个方式必须确保你的串口设备(包括发送端)支持RTS/CTS引脚,而且发送端也要配置成RTS/CTS流控模式,不然没用哦。


3. DSR/DTR 流控(特殊场景备选)

DSR是发送端的引脚(表示发送端就绪),DTR是我们这边的引脚(表示我们就绪)。原本是用来检测设备是否在线的,偶尔也能当流控用,但不如RTS/CTS靠谱,除非你设备只支持这个。

手动控制示例

import serial
import time

ser = serial.Serial(
    port='COM3',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_1,
    bytesize=serial.EIGHTBITS,
    dsrdtr=False  # 关闭自动控制
)

received_data = b''
threshold = 13

try:
    ser.setDTR(True)  # 初始告诉发送端:我们就绪,可以发
    while True:
        if ser.in_waiting > 0:
            chunk = ser.read(ser.in_waiting)
            received_data += chunk
            print(f"当前已接收: {len(received_data)} 字节")
            
            if len(received_data) >= threshold:
                print("⚠️ 达到阈值,拉低DTR停止接收")
                ser.setDTR(False)  # 告诉发送端:我们忙,别发了
                # 处理数据
                time.sleep(2)
                print("✅ 处理完成,拉高DTR恢复接收")
                ser.setDTR(True)
                received_data = b''
finally:
    ser.close()

同样,这个需要发送端监听DSR引脚的状态,当DSR变低就停发,得提前和发送端的逻辑匹配好。


最后给你个选择建议

  • 要是你的串口设备没硬件流控引脚(比如便宜的USB转串口模块),直接选Xon/Xoff软件流控。
  • 要是追求稳定、实时性,优先选RTS/CTS硬件流控,工业场景都是用这个。
  • DSR/DTR尽量只用来检测设备就绪,除非特殊情况,别当流控用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:47:56