做蓝牙制作的同学都知道,蓝牙模组与创建之间都是大部分是借助UART接口来进行通信的,一般遇到的难题就两大类:第一类是蓝牙驱动、固件问题,这种没办法,只能找技术支持,尤其是固件,一般不开源;第二类就是串口上的问题,这里要排查的点就很多了,比如串口号、波特率、数据位停止位等等,这些确实都有可能导致串口通信出现问题,但很崩溃的是——明明蓝牙模块和主控芯片的波特率、数据位、停止位都配置对了,却总会出现数据丢失、乱码的情况。
排查到最终才发现,罪魁祸首往往是被忽略的“硬件流控”,而CTS和RTS这两个不起眼的信号,正是解决问题的关键。今天就带大家扒一扒这两个信号的本质,以及它们在蓝牙通信中到底扮演着怎样的角色。
UART与蓝牙的“通信纽带”-CTS&RTS
在聊CTS和RTS之前,我们还是要反复强调一个基础逻辑:蓝牙模块(无论是经典蓝牙还是BLE)与主控(比如STM32、RK3568)之间的通信,绝大多数情况下都是通过UART接口实现的。UART作为一种异步串行通信协议,核心是通过“发送线(TX)”和“接收线(RX)”完成数据传输。
但问题来了:UART是“异步”的——发送方和接收方哪怕约定了相同的波特率用于收发,但各自的处理速度并不一定匹配。比如,蓝牙模块接收手机发来的数据后,必须通过UART快速传给主控芯片,可主控此时可能正在处理其他任务(比如控制传感器或者接收其他外设发来的数据),暂时“忙不过来”接收数据。这时候倘若发送方还在一个劲地发数据,接收方的缓冲区就会溢出,数据自然就丢了。
这就是“流控”要解决的核心问题:协调发送方和接收方的速度,确保“发送不赶工,接收不堵车”。而CTS和RTS,就是硬件层面实现流控的“左右手”。
CTS与RTS到底是什么?
数据流。就是CTS(Clear to Send,允许发送)和RTS(Request to Send,请求发送)是UART接口中除了TX、RX之外的两个流控信号,它们老是“成对出现”,但作用方向相反,我们可以用“请求-应答”的逻辑来理解。他们通常被视作完成硬件流控的关键信号,这里讲到的“流”,当然指的
1. 信号本质:单向控制,各司其职
这两个信号都是“电平信号”(通常是TTL电平,高电平高效或低电平有效可配置,具体看模块手册),但控制方向完全相反:
- RTS:接收方→发送方否准备好接收,你要不要发”。比如MCU作为接收方时,会利用RTS信号告诉蓝牙模块(发送方):“我准备好了,你可以发数据了”或者“我忙,你先别发”。就是:由“接收数据的设备”发给“发送数据的设备”,核心作用是“我
- CTS:发送方→接收方:由“发送数据的设备”发给“接收数据的设备”,核心作用是“我收到你的请求了,我要不要开始发”。比如蓝牙模块作为发送方时,会通过CTS信号回应MCU(接收方)的RTS请求:“我收到你准备好的信号了,我马上发”或者“我这边数据还没准备好,你再等等”。
简单来说:RTS是“接收方的状态通知”,CTS是“发送方的响应确认”,二者配合形成一个完整的“握手”机制。
2. 工作机制:用一个场景看懂“握手流程”
我们以“蓝牙模块(发送方)向MCU(接收方)传输数据”为例,拆解一下CTS和RTS的完整工作流程,假设高电平表示“有效”:
- 初始状态:蓝牙模块和MCU的RTS、CTS均为低电平,双方处于“待命”状态,MCU的UART接收缓冲区为空。
- 接收方请求将自己的RTS信号置为高电平——相当于告诉蓝牙模块:“我准备好了,你有数据的话可以发了”。就是:MCU完成当前任务,空闲下来,准备接收数据,于
- 发送方响应将自己的CTS信号置为高电平——相当于回复MCU:“我收到你的通知了,我这就开始发内容”。就是:蓝牙模块检测到MCU的RTS为高电平,知道对方“有空”,于
- 数据传输:蓝牙模块利用TX线向MCU的RX线发送数据,MCU持续接收并将素材存入缓冲区。
- 接收方忙,暂停传输:当MCU的接收缓冲区快满(比如达到80%阈值),MCU立即将RTS信号置为低电平——告诉蓝牙模块:“我快装不下了,赶紧停!”
- 发送方暂停:蓝牙模块检测到RTS变为低电平,立即停止发送数据(此时可能会缓存少量待发数据),同时将CTS置为低电平——告知MCU:“我收到暂停信号了,已经停了”。
- 接收方空闲,恢复传输:MCU处理完缓冲区中的数据,缓冲区空出足够空间后,再次将RTS置为高电平,重复步骤3-6,直到所有数据传输完成。

关键提醒“低电平代表允许”,否则会出现完全相反的通信故障。就是:不同模块的CTS/RTS电平奏效方向可能不同(比如有些是低电平实用),开发时一定要先查模块手册,确认“高电平代表允许”还
什么时候必须开CTS/RTS?
“必选项”,否则一定会出挑战:就是有些同学会问:“我之前做容易的蓝牙数据传输,没接CTS和RTS也能用,是不是这两个信号可有可无?” 这其实是“运气好”——当数据量小、传输频率低时,接收方的缓冲区足以“暂存”数据,不会溢出。但在以下场景中,CTS/RTS硬件流控
1. 大文件传输场景
比如用蓝牙传输图片、日志文件等大尺寸数据,发送方会以“连续流”的方式发信息,此时MCU假如没有足够快的处理速度,缓冲区会在几毫秒内溢出,导致文件传输中断或信息损坏。这时候CTS/RTS的“速度协调”作用就至关重要。
2. 高实时性场景
比如工业控制中,蓝牙模块需要实时传输传感器资料(如温度、压力)给MCU,MCU同时还要执行控制逻辑。此种情况下MCU的“空闲时间”不确定,可能突然进入忙碌状态,此时如果没有流控,传感器数据就会丢失,影响控制精度。
3. 多设备级联场景
若是MCU同时连接了蓝牙模块、GPS模块、串口屏等多个UART设备,MCU需要在多个设备之间“切换处理”,对每个设备的响应速度都会下降。此时给每个UART设备都配置CTS/RTS流控,能确保每个设备的内容都不会由于MCU“忙不过来”而丢失。
注意事项
搞懂了原理,实际制作中还要注意这几个细节,避免踩坑:
1. 硬件接线:
CTS和RTS是“交叉连接”的,很多人一不注意就会接错线,导致通信失败。正确的接线逻辑是:
DTE1(如蓝牙模块) | DTE2(如MCU) |
TX(发送) | RX(接收) |
RX(接收) | TX(发送) |
CTS(接收方状态输入) | RTS(发送方状态输出) |
RTS(发送方状态输出) | CTS(接收方状态输入) |
简单记:A的CTS接B的RTS,A的RTS接B的CTS,和TX/RX的交叉逻辑一致。

2. 软件部署
硬件接好后,软件上需在MCU的UART初始化代码中开启“硬件流控模式”,同时配置RTS和CTS对应的GPIO引脚为“复用作用”(不同MCU的设置方式不同,比如STM32必须设置USART_CR3寄存器的CTSE和RTSE位)。如果只接了硬件却没开软件配备,流控信号相当于“闲置”,还是会出现数据丢失。
3. 缓冲区阈值
MCU的UART接收缓冲区通常是环形缓冲区,我们需设置一个“触发阈值”——当缓冲区数据量达到阈值时,就将RTS置为低电平暂停接收。阈值设置不能太满(比如100%满才暂停,可能来不及),也不能太松(比如20%满就暂停,会降低传输效率),通常建议设置为缓冲区大小的70%-80%,具体根据实际资料传输速度调整。
总结
CTS/RTS不是“可选项”,而是“可靠性保障”,尤其是在蓝牙中,他几乎是"必选项"
很多蓝牙开发的“玄学故障”,本质上都是基础通信机制没吃透。CTS和RTS看似是两个容易的信号,却承载着UART通信的“速度协调”核心功能——它们就像交通路口的“红绿灯”,确保发送方和接收方的数据流“有序通行”。
下次再遇到蓝牙UART通信的数据丢失、乱码问题,别再只盯着波特率和数据位了,先检查一下CTS/RTS的硬件接线和软件配置,大概率能找到问题所在。毕竟,可靠的通信,从来都离不开这些“细节里的功夫”。