一句话结论:灵-TR5mini-T 对 MCU 来说仍然是 TTL 串口,MCU 按 UART 收发即可;但无线链路不是一根真正的线,产品要稳定,必须把接线、参数、应用层协议、电源和 PCB 布局一起做好。
很多客户第一次用无线串口模块,第一反应都是:是不是把原来的串口线换成无线就行?
大方向没错。只是无线链路会重新打包,模块也是半双工收发,接收端字节间隔可能不均匀。所以项目真正稳定,不只靠“能收到数据”,还要把供电、PCB、参数一致性、地址 ID 和数据校验一起考虑进去。
本文以蜂鸟无线的灵-TR5mini-T 为例,说明 2.4GHz 无线串口模块的基本用法,并给出 STM32、51 单片机、串口指令设置、配对和校验的参考例程。
一、先看清 灵-TR5mini-T 的工作边界
灵-TR5mini-T 是一款微型 2.4GHz 无线串口收发模块,采用 GFSK 调制,自带陶瓷天线。模块对 MCU 侧提供 UART TTL 串口,MCU 只需要按串口方式收发数据;模块内部负责把串口数据打包,通过 2.4GHz 无线链路发出去。
使用时要记住几个关键点:
- 供电电压:2.2-3.6V,典型 3.3V。
- 串口电平:TTL 电平,注意不要直接接 5V 串口电平。
- 默认通信波特率:9600bps。
- 设置模式波特率:强制 9600bps,8N1,和当前无线通信波特率无关。
- 工作频段:2400-2527MHz,128 个信道可设,默认信道 0x53,对应 2483MHz。
- 空中速率:250kbps,和 UART 波特率不是同一个参数。
- 模块是半双工通信,不建议两端同时发送。
- 模块内部会按随机数据量重新打包,空中包一次最多 7 个字节;接收端收到的字节间隔可能不均匀。
最后一点很重要。比如发送端一次通过 UART 发送 123456789,接收端最终能收到这 9 个字节,但它可能不是以“连续无间隔的一整包”形式到达 MCU。工程上建议接收端用“串口接收 + 定时器超时”来判断一包结束,例如连续 10ms 没有新字节,再认为当前业务包接收完成。
二、硬件连接:通信模式、设置模式、休眠模式
灵-TR5mini-T 常用引脚如下:
| 引脚 | 作用 | 说明 |
|---|---|---|
| V | 电源正 | 2.2-3.6V,典型 3.3V |
| R/RXD | 模块数据输入 | 接 MCU 的 TXD |
| T/TXD | 模块数据输出 | 接 MCU 的 RXD |
| S/SET | 设置模式控制 | 低电平进入设置模式,高电平或悬空为通信模式 |
| C/CS | 工作/休眠控制 | 低电平工作,高电平或悬空休眠 |
| G/GND | 电源负 | 与 MCU 共地 |
通信模式接法:
MCU TXD -> 灵-TR5mini-T RXD/R
MCU RXD <- 灵-TR5mini-T TXD/T
MCU GND -> 灵-TR5mini-T GND/G
3.3V -> 灵-TR5mini-T VCC/V
SET/S -> 高电平或悬空
CS/C -> 低电平
设置模式接法:
SET/S -> 低电平
CS/C -> 低电平
UART -> 9600bps, 8 data bits, no parity, 1 stop bit
休眠模式:
CS/C -> 高电平或悬空
从休眠唤醒到工作,规格书给出的典型时间约 12ms;上电初始化后,建议等待约 0.5s 再开始通信。设置参数完成后,把 SET 拉高回到通信模式,也建议等待约 0.5s 再收发数据。
三、STM32 发送 123456789 示例
下面示例使用 STM32 HAL 库。假设 灵-TR5mini-T 使用默认 9600bps,MCU 的 USART1 已初始化为 9600、8N1。
发送端代码:
#include "main.h"
#include <string.h>
extern UART_HandleTypeDef huart1;
void TR5mini_Send_Test(void)
{
/* 测试数据:发送端 MCU 通过 UART 写入模块 RXD/R 引脚 */
const uint8_t data[] = "123456789";
/*
* sizeof(data) 包含字符串末尾的 '\0',
* 所以实际发送长度要减 1,只发送 9 个 ASCII 字节。
*/
HAL_UART_Transmit(&huart1, (uint8_t *)data, sizeof(data) - 1, 100);
}
接收端如果只验证透传是否成功,可以先用串口助手连接接收端模块的 TXD/RXD;如果接到 STM32,建议不要只依赖 UART IDLE 中断直接判包,而是加一个定时器超时。
接收端参考逻辑:
#include "main.h"
#include <string.h>
#include <stdint.h>
extern UART_HandleTypeDef huart1;
#define RX_BUF_SIZE 64
static uint8_t rx_buf[RX_BUF_SIZE]; /* 接收缓存,保存收到的 UART 字节 */
static uint8_t rx_ch = 0; /* HAL 每次中断接收 1 个字节 */
static volatile uint16_t rx_len = 0; /* 当前已经收到的字节数 */
static volatile uint32_t last_rx_tick = 0; /* 最近一次收到字节的时间 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1) {
if (rx_len < RX_BUF_SIZE) {
/* 先把本次收到的字节放进缓存,再继续打开下一次接收 */
rx_buf[rx_len++] = rx_ch;
}
/* 记录最后一个字节到达时间,后面用来做超时判包 */
last_rx_tick = HAL_GetTick();
/* 重新启动 1 字节中断接收,否则只能收到第 1 个字节 */
HAL_UART_Receive_IT(&huart1, &rx_ch, 1);
}
}
void TR5mini_Rx_Start(void)
{
/* 上电或初始化 UART 后调用一次,开始接收第 1 个字节 */
rx_len = 0;
HAL_UART_Receive_IT(&huart1, &rx_ch, 1);
}
void TR5mini_Rx_Poll(void)
{
/*
* 连续 10ms 没有新字节,就认为当前一包数据已经收完。
* 无线模块内部会分包转发,实际产品建议再配合帧头、长度和 CRC。
*/
if (rx_len > 0 && (HAL_GetTick() - last_rx_tick) >= 10) {
if (rx_len == 9 && memcmp(rx_buf, "123456789", 9) == 0) {
/* 收到完整测试数据,可在这里点亮 LED 或执行业务动作 */
}
/* 处理完一包后清空长度,准备接收下一包 */
rx_len = 0;
}
}
工程提示:上面代码是演示“10ms 无新字节认为一包结束”的思路。实际项目里,最好使用后文的帧头、长度和 CRC 来判断一帧是否完整。
123456789,接收端可能分成几段到达,并用“10ms 超时判包”的时间标尺解释为什么不能只看 UART IDLE。四、51 单片机发送 123456789 示例
下面以传统 8051、11.0592MHz 晶振、9600bps 为例。灵-TR5mini-T 默认 9600bps,所以不改模块参数也能测试。
#include <reg52.h>
void Uart_Init_9600(void)
{
SCON = 0x50; /* 8位 UART,可变波特率,允许接收 */
TMOD &= 0x0F;
TMOD |= 0x20; /* 定时器1,方式2,8位自动重装 */
TH1 = 0xFD; /* 11.0592MHz 下 9600bps */
TL1 = 0xFD; /* 初值同 TH1 */
TR1 = 1; /* 启动定时器1,串口波特率开始工作 */
ES = 0; /* 本例只演示发送,先关闭串口中断 */
}
void Uart_Send_Byte(unsigned char dat)
{
SBUF = dat; /* 写入发送缓冲寄存器,硬件开始发送 */
while (TI == 0); /* 等待本字节发送完成 */
TI = 0; /* 清发送完成标志,准备发送下一个字节 */
}
void Uart_Send_String(const char *s)
{
while (*s) {
/* 逐字节发送,直到遇到字符串结束符 '\0' */
Uart_Send_Byte((unsigned char)*s++);
}
}
void main(void)
{
unsigned int i;
Uart_Init_9600();
while (1) {
/* 通过 51 的 TXD 发给灵-TR5mini-T,模块再无线转发 */
Uart_Send_String("123456789");
/* 简单延时,避免一直占用无线链路 */
/* 实际项目可换成定时器或业务触发 */
for (i = 0; i < 60000; i++);
}
}
如果使用 12MHz 或其他晶振,定时器重装值需要重新计算。接线时同样是 51 TXD 接模块 RXD,51 RXD 接模块 TXD,并且共地。
五、串口指令设置参数示例
灵-TR5mini-T 支持通过上位机软件或串口指令设置参数。用 MCU 或串口助手设置时,先进入设置模式:
SET/S = 低电平
CS/C = 低电平
串口 = 9600bps, 8N1
参数设置帧固定 18 字节,格式如下:
| 字节位置 | 字段 | 说明 |
|---|---|---|
| 1 | 0xAA | 命令字节 |
| 2 | 0x5A | 写参数命令字节 |
| 3-4 | Product ID | 产品型号 ID,只读,设置无效 |
| 5-6 | Net ID | 组网 ID,可读写,必须相同才能通信 |
| 7 | Nc | 保留 |
| 8 | RF Power | 发射功率,0-6 共 7 档,默认 0 为最大 |
| 9 | Nc | 保留 |
| 10 | Baud | 串口波特率,0-7 |
| 11 | Nc | 保留 |
| 12 | RF Channel | RF 信道,0-127 对应 2400-2527MHz |
| 13-15 | Nc | 保留 |
| 16 | Length | 固定 0x12 |
| 17 | Nc | 保留 |
| 18 | CheckSum | 前 17 字节相加,取低 8 位 |
波特率字段对应关系:
| Baud 值 | 波特率 |
|---|---|
| 0 | 600 |
| 1 | 1200 |
| 2 | 2400 |
| 3 | 4800 |
| 4 | 9600 |
| 5 | 19200 |
| 6 | 38400 |
| 7 | 115200 |
发射功率字段对应关系:
| RF Power 值 | 规格书对应功率 |
|---|---|
| 0 | 10dBm |
| 1 | 6dBm |
| 2 | 3dBm |
| 3 | 2dBm |
| 4 | 1dBm |
| 5 | 0dBm |
| 6 | -8dBm |
规格书示例写参数命令:
AA 5A 00 00 12 34 00 01 00 04 00 53 00 00 00 12 00 B4
含义如下:
AA 5A:写参数帧头。12 34:Net ID,发送端和接收端必须一致。01:发射功率,对应 6dBm。04:串口波特率 9600bps。53:RF 信道,十进制 83,对应 2483MHz。12:本包长度,固定 0x12,即 18 字节。B4:前 17 字节校验和的低 8 位。
模块收到后,蓝色 LED 会闪一下,并返回类似:
AA 5B 4C 05 12 34 00 01 00 04 00 53 00 00 00 12 00 06
返回帧头从 AA 5A 变为 AA 5B,Product ID 会变为厂家默认编号,其余关键参数按命令回显。
查询参数命令:
AA 5C 00 00 00 00 00 00 00 00 00 00 00 00 00 12 00 18
查询版本号命令:
AA 5D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07
恢复出厂默认参数命令:
AA 5A 00 00 00 00 00 00 00 04 00 53 00 00 00 12 00 6D
写指令时要特别注意两点:
- CheckSum 是前 17 字节相加后取低 8 位,不能漏算保留字节。
- 多组模块互不干扰时,优先同时区分 Net ID 和 RF 信道。Net ID 相当于软件分组,信道相当于频率分组。
信道不要使用 16 的倍数和 0,例如 0x00、0x10、0x40 这类信道不建议使用。
STM32 发送设置命令示例:
uint8_t tr5mini_cfg[] = {
0xAA, 0x5A, /* 写参数命令帧头 */
0x00, 0x00, /* Product ID:设置时填 0 即可 */
0x12, 0x34, /* Net ID:两端一致才能通信 */
0x00, /* 保留字节 */
0x01, /* RF Power:6dBm */
0x00, /* 保留字节 */
0x04, /* Baud:9600bps */
0x00, /* 保留字节 */
0x53, /* RF Channel:2483MHz */
0x00, 0x00, 0x00, /* 保留字节 */
0x12, /* Length:固定 18 字节 */
0x00, /* 保留字节 */
0xB4 /* CheckSum:前 17 字节累加取低 8 位 */
};
/* SET/S 拉低进入设置模式后,再发送这 18 个字节 */
HAL_UART_Transmit(&huart1, tr5mini_cfg, sizeof(tr5mini_cfg), 100);
如果要在程序里动态生成命令,可以用下面的校验函数:
uint8_t Sum8(const uint8_t *buf, uint8_t len)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
/* 按字节累加,保留字节也要算进去 */
sum += buf[i];
}
/* 只取低 8 位作为模块参数帧校验值 */
return (uint8_t)(sum & 0xFF);
}
void TR5mini_Fill_Checksum(uint8_t frame[18])
{
/* frame[17] 是第 18 字节,也就是 CheckSum 字段 */
frame[17] = Sum8(frame, 17);
}
六、配对怎么做:让接收端识别允许的地址
很多遥控、控制器、传感器项目都会问:无线串口模块怎么配对?
从工程角度看,配对本质上是接收端只接受“允许的发送端”。灵-TR5mini-T 已经提供了 Net ID 和 RF 信道这种分组能力,在此基础上,应用层还可以在数据包里加入地址 ID,实现更灵活的配对。
方案一:应用层地址 ID 配对,推荐用于产品业务
发送端在业务数据前面加入自己的地址 ID,例如:
帧头 地址ID 序号 长度 数据 CRC
A5 5A 12 34 01 09 31 32 ... 39 xxxx
其中 31 32 ... 39 就是 ASCII 的 123456789。
接收端保存允许的地址 ID,例如 0x1234。收到数据后先检查:
- 帧头是否正确。
- 长度是否正确。
- CRC 是否正确。
- 地址 ID 是否在允许列表里。
- 序号是否重复。
只有全部通过,才执行业务动作。
配对流程可以这样设计:
1. 接收端长按按键,进入学习模式,LED 慢闪。
2. 发送端发送带自身地址 ID 的配对帧。
3. 接收端校验帧头、长度和 CRC。
4. 校验通过后,把地址 ID 保存到 Flash/EEPROM。
5. 接收端退出学习模式,后续只响应这个地址 ID。
这种方案的优点是灵活:一个接收端可以学习多个发送端,也可以删除单个发送端;缺点是 MCU 侧需要写一套小协议。
方案二:模块参数分组配对,推荐用于简单点对点或小批量分组
如果产品只需要简单分组,可以使用灵-TR5mini-T 的 Net ID 和 RF 信道:
A 组:Net ID = 0x1234,信道 = 0x53
B 组:Net ID = 0x5678,信道 = 0x55
同组发送端和接收端设置相同 Net ID、相同 RF 信道,才能通信。不同组设置不同 Net ID 或不同信道,可以降低互相收到数据的概率。
这种方案的优点是简单,配置好模块参数后 MCU 仍然按普通串口透传使用;缺点是管理不如应用层地址 ID 灵活,后期如果要做“一拖多”“多遥控器学习”“删除单个遥控器”等功能,通常还要回到方案一。
实际产品中,两种方案可以组合使用:模块层用 Net ID + 信道做基础隔离,应用层再用地址 ID 做业务配对。
七、数据校验建议:无线透传不等于业务可靠协议
灵-TR5mini-T 负责把串口数据通过无线链路透传,但业务层如果要提高可靠性,建议自己增加帧格式和校验。推荐帧格式如下:
帧头 地址ID 序号 长度 数据区 CRC16
A5 5A 2字节 1字节 1字节 0-N字节 2字节
示例:发送 123456789
A5 5A 12 34 01 09 31 32 33 34 35 36 37 38 39 CRC_L CRC_H
建议至少做以下四件事:
- 加帧头:让接收端能在连续字节流里找到一帧开始位置。
- 加长度:不要靠“收到几个字节”来猜业务包大小。
- 加 CRC8 或 CRC16:比简单累加和更适合判断数据是否被破坏。
- 加序号和 ACK/重发:控制类产品可以避免重复执行和漏执行。
CRC16/Modbus 参考代码:
uint16_t CRC16_Modbus(const uint8_t *buf, uint16_t len)
{
uint16_t crc = 0xFFFF;
for (uint16_t pos = 0; pos < len; pos++) {
/* 先把当前字节异或进 CRC 低 8 位 */
crc ^= buf[pos];
/* 每个字节处理 8 个 bit */
for (uint8_t i = 0; i < 8; i++) {
if (crc & 0x0001) {
/* 低位为 1 时右移后再异或多项式 0xA001 */
crc >>= 1;
crc ^= 0xA001;
} else {
/* 低位为 0 时只右移 */
crc >>= 1;
}
}
}
/* Modbus CRC 常用低字节在前、高字节在后的发送顺序 */
return crc;
}
ACK/重发可以按下面思路做:
1. 发送端发送一帧,序号 seq 加 1。
2. 接收端校验通过后,返回 ACK + seq。
3. 发送端在设定超时时间内收到 ACK,认为成功。示例可先按 30-100ms 验证,实际项目需按数据量、波特率和业务响应时间调整。
4. 超时未收到 ACK,重发同一 seq,最多重发 2-3 次。
5. 接收端如果收到重复 seq,只回 ACK,不重复执行业务动作。
由于模块是半双工,发送端发完数据后不要立刻继续占用串口,建议留出接收端回复 ACK 的时间。规格书给出的收发转换理论时间约 4ms,应答式双向通信中可以先按 10ms 级别延时验证,再根据实际项目调整。
八、电源和 PCB 建议:无线问题经常不是无线本身
无线串口模块能不能稳定工作,供电和 PCB 影响很大。很多“距离近”“偶发丢包”“上电正常、带负载就异常”的问题,最后查下来不是参数错,而是电源瞬态、地回流、数字噪声或天线周边布局不合适。
1. 电源线要短、宽、近
灵-TR5mini-T 典型使用 3.3V 供电。模块发射时电流会变化,如果电源线又长又细,走线阻抗会把电流变化变成电压波动,送到模块 VCC 上。万用表往往看不出这种瞬态跌落,示波器才能看清楚。
建议这样处理:
- 模块 VCC 走线尽量短、尽量宽,不要绕远路。
- 模块供电脚附近放去耦电容,常用做法是 0.1uF 贴近引脚,再按整板电源情况增加 1uF-10uF 储能电容。
- 如果同一块板上有继电器、电机、电磁阀、蜂鸣器、背光等负载,模块供电不要和大电流负载共用一段又细又长的电源路径。
- 调试“发射瞬间重启、距离忽远忽近、接收乱码”时,用示波器探头直接量模块 VCC 和 GND,重点看发射瞬间有没有跌落、尖峰或纹波。
2. 数字区、射频区、负载区不要混在一起
PCB 布局时,先把电路分区:MCU 和高速数字线放数字区,灵-TR5mini-T 和天线周边作为无线模块区,继电器、电机驱动等大电流部分单独放负载区。容易产生噪声的部分尽量远离模块和天线。
布局时可以按这个顺序检查:
- MCU、晶振、显示屏排线等数字噪声源,不要紧贴模块天线一侧。
- 继电器、电机、蜂鸣器、DC-DC 电感等干扰源,尽量远离模块和串口线。
- 模块附近的滤波网络、去耦电容要就近放,不要跨半块板才接到模块。
- 同一功能的电路尽量集中,减少信号环路面积。
这类布局不是为了好看,而是为了减少噪声耦合。对 RF 模块来说,输入引线、长电源线、长串口线、悬空金属件,都可能变成“意外天线”。
3. 地线要让回流路径清楚
地线不是理想的 0 欧姆。电流经过地线时会产生压降,多个电路共用一段地线,就可能形成公共阻抗耦合。数字电流、负载电流、模块电流混在同一条窄地线上,很容易把噪声带到模块参考地。
建议:
- 尽量使用连续地平面,让数字信号有就近的回流路径。
- 不要在模块和 MCU 的关键信号下方随意切断地平面。
- 数字区和模拟/射频敏感区可以在布局上分开,最后在合适的电源地位置汇总。
- 大电流负载的回流路径不要穿过模块地。
- 空间允许时,模块周边可以用地铜和过孔围出相对干净的参考区域,但不要破坏天线需要的净空。
如果板子是两层板,更要注意地回流路径。表面看 TXD/RXD 只是一根线,实际上信号电流还要从地返回;回流绕远了,环路面积变大,辐射和抗干扰都会变差。
4. 走线尽量短,避免平行长距离耦合
附件《开发必看》里提到一个很实用的原则:信号线尽可能短,过孔尽量少,不相容的信号线尽量远离,避免长距离平行走线。
落到灵-TR5mini-T 项目里,可以这样做:
- MCU 到模块的 UART 线尽量短。
- UART 线不要贴着继电器线圈、电机线、DC-DC 开关节点走。
- 不同层的信号线如果必须交叉,尽量垂直交叉,减少耦合面积。
- 走线转角尽量用 135 度或圆滑转角,不建议用尖锐直角。
- 模块天线附近不要铺大面积金属、走高速线或放高器件;如果使用自带陶瓷天线,更要留出天线侧空间。
5. 先做裸板基准,再逐步加外壳和负载
如果样机通信不稳定,不要一开始就怀疑模块坏了。建议按“裸板 -> 加外壳 -> 加负载动作 -> 实际安装环境”的顺序测试。
测试时记录这些条件:
- 供电电压和电源类型。
- Net ID、RF 信道、串口波特率。
- 天线方向和模块摆放方向。
- 是否装外壳,外壳内是否有电池、金属件、屏蔽件。
- 继电器、电机等负载动作时是否影响通信。
- 固定距离下连续收发多少次,成功率是多少。
这样客户反馈问题时,工程师能快速判断是参数、供电、天线、PCB、负载干扰,还是现场环境导致。
九、调试建议:先让模块跑通,再接入业务板
排查无线串口问题时,建议按下面顺序:
- 两个模块先用电脑串口助手测试,确认默认参数下能收发。
- 确认供电稳定,发射瞬间电压不要跌落;万用表不一定能看到瞬态跌落,必要时用示波器看 VCC。
- 确认 SET 回到通信模式,CS/C 为低电平工作状态。
- 确认两端 Net ID、RF 信道、串口波特率一致。
- 确认 MCU TXD/RXD 是否交叉连接,GND 是否共地。
- 用逻辑分析仪看 MCU UART 线上是否真的发出了
123456789。 - 接收端不要只用 STM32 IDLE 中断直接判包,建议加 1-10ms 定时器超时。
- 多组设备同时工作时,不要只改 Net ID,也建议错开 RF 信道。
如果客户反馈“距离近、偶发不通、接收乱码”,优先检查供电、天线环境、串口波特率、SET/CS 状态和参数一致性。无线串口模块本身是链路工具,产品最终可靠性还要靠电源设计、天线位置、协议校验和异常重发共同保证。
十、总结
灵-TR5mini-T 的使用可以分成四层理解:
第一层是硬件连接:3.3V 供电、TTL 串口、TX/RX 交叉、GND 共地,通信时 CS/C 拉低,SET/S 保持高电平或悬空。
第二层是模块参数:默认 9600bps 可直接通信;需要分组或避开干扰时,通过设置模式配置 Net ID、RF 信道、功率和串口波特率。
第三层是业务协议:如果产品需要配对、校验、重发和防重复执行,就在应用层增加地址 ID、帧头、长度、CRC、序号和 ACK。
第四层是电源和 PCB:模块供电要短、宽、稳,地回流要清楚,天线周边要留空间,干扰源不要贴着模块和天线走。
把这四层分清楚,STM32、51 或其他 MCU 使用灵-TR5mini-T 就不会复杂:MCU 仍然写串口程序,模块负责无线透传,产品可靠性由“正确接线 + 正确参数 + 应用层协议 + 电源和 PCB 设计”共同决定。