3、硬件流控(RTS/CTS)实战:开启硬件流控后,烧录速度能提升多少?手把手教你接线与配置。

上一章我们聊了波特率,说白了就是让收发双方约定好一个节奏。但实际干活的时候,你会发现一个问题——发送端噼里啪啦往外丢数据,接收端却来不及处理,缓冲区一满,数据就丢了。

这时候,硬件流控就派上用场了。它就像两个人在打电话,一个人说“你慢点说,我记一下”,另一个人就停下来等。RTS 和 CTS 就是干这个的。

3.1 什么是 RTS/CTS?

RTS(Request To Send)和 CTS(Clear To Send)是串口硬件流控的两根信号线。它们的作用很简单:

  • RTS:发送端告诉接收端“我要发数据了,你准备好了吗?”
  • CTS:接收端回答“准备好了,你发吧”或者“等一下,我还没消化完”。

我刚开始做嵌入式的时候,总觉得这玩意儿多余。直到有一次,我在一个项目里用 921600 波特率烧录固件,结果 10 次里有 3 次校验失败。查了半天,发现是接收端的缓冲区太小,数据一快就溢出了。从那以后,但凡高速烧录,我必开硬件流控。

核心结论:硬件流控不是“锦上添花”,而是高速烧录的“保命手段”。没有它,高波特率下的数据完整性全靠运气。

3.2 硬件流控能提升多少速度?

很多人以为开了硬件流控会变慢,因为要等握手信号。其实恰恰相反——硬件流控能让你用更高的波特率,而且不出错。

我做过一组对比测试,用的是 STM32F103 通过 UART1 烧录固件,目标芯片是另一块 STM32。结果如下:

测试条件 波特率 烧录时间 成功率
无流控 115200 32.5s 100%
无流控 460800 8.1s 72%
无流控 921600 4.0s 31%
硬件流控 921600 4.2s 100%

看到了吗?无流控下 921600 的成功率只有 31%,基本没法用。但开了硬件流控后,同样的波特率,成功率直接拉满到 100%,时间只多了 0.2 秒。这 0.2 秒是握手信号的开销,但换来了 3 倍以上的可靠性提升。

我的建议:如果你现在的烧录速度在 115200 以下,硬件流控的意义不大。但一旦超过 230400,我强烈建议你加上。说白了,硬件流控不是用来“提速”的,而是用来“保速”的——让你敢用更高的波特率。

3.3 接线方法:手把手教你连

硬件流控的接线其实不复杂,但很多人栽在“交叉”还是“直连”上。我画了一张图,你看完就明白了。

硬件流控 RTS/CTS 接线示意图 设备 A (主机/烧录器) 设备 B (目标芯片) TXD → RXD RXD ← TXD RTS → CTS CTS ← RTS GND —— GND 关键:RTS 接对方的 CTS,CTS 接对方的 RTS,不要接反!

接线口诀就一句话:RTS 对 CTS,CTS 对 RTS,交叉连接。和 TXD/RXD 的交叉逻辑一样。

具体步骤:

  1. 把设备 A 的 RTS 引脚接到设备 B 的 CTS 引脚
  2. 把设备 A 的 CTS 引脚接到设备 B 的 RTS 引脚
  3. GND 必须共地,这是所有信号的基础
  4. TXD/RXD 正常交叉连接

我曾经踩过的坑:有一次我用的 USB 转串口模块是 CH340,它虽然标了 RTS 和 CTS,但实际只支持 DTR 和 RTS 的软件模拟,硬件流控根本不起作用。后来换了 FT232 才搞定。所以,选硬件的时候一定要确认——芯片手册里明确写了“硬件流控支持”才行。

3.4 软件配置:代码里怎么开?

硬件接好了,软件也得配。不同平台配置方式不一样,但思路是相通的。我以 STM32 HAL 库和 Linux 为例。

3.4.1 STM32 HAL 库配置

// 初始化 UART 句柄
UART_HandleTypeDef huart1;

// 配置参数
huart1.Instance = USART1;
huart1.Init.BaudRate = 921600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;

// 关键:开启硬件流控
huart1.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;

// 初始化
HAL_UART_Init(&huart1);

注意 HwFlowCtl 这个参数。如果你只用了 RTS 或 CTS 中的一根,可以选 UART_HWCONTROL_RTS 或 UART_HWCONTROL_CTS。但我的习惯是两根都接上,选 UART_HWCONTROL_RTS_CTS,这样双向流控都生效。

3.4.2 Linux 下配置

Linux 下用 termios 结构体配置,稍微麻烦一点:

#include <termios.h>

struct termios tty;
int fd = open("/dev/ttyUSB0", O_RDWR);

// 获取当前配置
tcgetattr(fd, &tty);

// 设置波特率 921600
cfsetospeed(&tty, B921600);
cfsetispeed(&tty, B921600);

// 开启硬件流控
tty.c_cflag |= CRTSCTS;  // 使能 RTS/CTS 流控

// 应用配置
tcsetattr(fd, TCSANOW, &tty);

这里 CRTSCTS 就是硬件流控的开关。我见过有人写 tty.c_cflag |= CRTSCTS 但忘了 tcsetattr,结果配置根本没生效。嗯,这种低级错误我也犯过。

3.5 验证方法:怎么知道流控生效了?

配置完了,怎么确认硬件流控真的在工作?我教你两个方法。

方法一:看波形

用示波器抓 RTS 和 CTS 引脚。正常工作时,你会看到 RTS 在发送数据前拉低(表示请求发送),CTS 在接收端准备好后拉低(表示允许发送)。如果两根线一直保持高电平,说明流控没开。

方法二:压力测试

用 921600 波特率连续烧录 10 次,记录每次的校验结果。如果 10 次全部通过,硬件流控基本没问题。如果偶尔失败,检查接线和配置。

我的经验值:硬件流控生效后,RTS 和 CTS 引脚上的信号应该是“动态”的——不是一直高或一直低,而是随着数据流不断跳变。如果看到的是死板的方波,那多半是软件配置没生效。

3.6 常见问题与避坑

  • 问题:开了流控反而烧录失败
    大概率是接线反了。RTS 和 CTS 交叉接,不是直连。
  • 问题:芯片不支持硬件流控
    有些低端 MCU 的 UART 外设没有 RTS/CTS 引脚。这时候只能用软件流控(XON/XOFF),或者降低波特率。
  • 问题:USB 转串口模块不支持
    我踩过这个坑。CH340G 的 RTS/CTS 是假的,只能做 GPIO 用。FT232RL、CP2102 的硬件流控是真实的。买模块前先查 datasheet。
  • 问题:线太长导致信号失真
    硬件流控对信号质量要求更高。如果线长超过 2 米,建议用屏蔽线,或者降低波特率。

好了,硬件流控这部分就讲到这里。你回去试试,把波特率拉到 921600,开硬件流控,看看烧录时间能压到多少。我等你反馈。