在 RS-232 串口通信中,除了数据线(TX 发送、RX 接收、GND 地线)外,还有一组控制信号线用于协调通信双方的数据传输。这些控制信号就是 RTS/CTS 和 DTR/DSR。
一、RTS/CTS(请求发送/清除发送)
这是最常用的硬件流控制方式,用于实时控制数据流,防止数据丢失。
信号定义
工作原理(数据流控制)
┌─────────┐ ┌─────────┐
│ 主机 │ ─── RTS ─────────→ │ 设备 │
│ (DTE) │ ←── CTS ────────── │ (DCE) │
└─────────┘ └─────────┘
数据流向:主机 ←── 数据 ─── 设备(从设备到主机)具体流程:
设备想发送数据给主机:
主机拉高 RTS → 表示"我准备好接收了"
设备检测到 RTS=高 后,拉高 CTS → 表示"我要开始发送了"
设备开始发送数据
如果主机处理不过来,拉低 RTS → 设备看到后立即停止发送
主机想发送数据给设备:
主机拉高 RTS → 请求发送
设备准备好接收后,拉高 CTS → 允许发送
主机开始发送数据
核心逻辑:RTS 和 CTS 都为高电平时,才允许发送数据
二、DTR/DSR(数据终端就绪/数据设备就绪)
这组信号主要用于设备初始握手和连接状态检测,而不是实时流控。
信号定义
工
┌─────────┐ ┌─────────┐
│ 主机 │ ─── DTR ─────────→ │ 设备 │
│ (DTE) │ ←── DSR ────────── │ (DCE) │
└─────────┘ └─────────┘典型应用场景(以 PC 连接 Modem 为例):
PC 开机/打开串口 → 拉高 DTR → 告诉 Modem:"我准备好了"
Modem 上电/就绪 → 拉高 DSR → 告诉 PC:"我也准备好了"
只有 DTR 和 DSR 都为高 时,双方才认为通信链路建立成功
如果 Modem 掉线,拉低 DSR → PC 知道设备断开
经典 Modem 通信流程:
PC Modem
│ │
│──────── DTR (高) ─────────→│ PC说:我准备好了
│←─────── DSR (高) ──────────│ Modem说:我也准备好了
│ │
│──────── RTS (高) ─────────→│ PC说:我想接收数据
│←─────── CTS (高) ──────────│ Modem说:好的,我开始发送
│←─────── 数据流 ────────────│ 数据传输中...
│ │
│←─────── CTS (低) ──────────│ Modem缓冲区满了,暂停
│ [暂停发送] │
│←─────── CTS (高) ──────────│ Modem可以继续了
│←─────── 数据流 ────────────│ 继续传输三、对比总结
四、硬件 vs 软件流控
五、在 usb-serial-for-android 中的使用
在 Android USB 串口开发中,这些信号通常通过以下方式控制:
UsbSerialPort port = ...;
// 设置 RTS 信号(请求接收数据)
port.setRTS(true); // 拉高 RTS
port.setRTS(false); // 拉低 RTS
// 设置 DTR 信号(声明主机就绪)
port.setDTR(true); // 拉高 DTR
port.setDTR(false); // 拉低 DTR
// 读取 CTS 状态(设备是否允许发送)
boolean cts = port.getCTS();
// 读取 DSR 状态(设备是否就绪)
boolean dsr = port.getDSR();
// 通常的打开流程
port.open(connection);
port.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);
port.setDTR(true); // 告诉设备我准备好了
port.setRTS(true); // 请求接收数据六、一句话总结
RTS/CTS = "红绿灯系统":实时控制数据能不能发,防止堵车(缓冲区溢出)
DTR/DSR = "签到系统":确认双方都在线,准备好开始工作
在现代串口通信中,RTS/CTS 是最常用的硬件流控方案,而 DTR/DSR 更多用于设备状态检测(如判断设备是否连接、是否就绪)。如果你的数据传输量大、速度快,强烈建议启用 RTS/CTS 流控,否则很容易丢数据!
Android 串口通信(四)RTS/CTS 与 DTR/DSR
https://lautung.com/archives/ZrnFSkj4