简介:这是一份面向51单片机学习者与物联网初学者的LoRa远程通信示例工程,演示如何利用51单片机串口(UART)与LoRa模块通过SPI接口实现低功耗远距离无线数据传输,适合正在做课程设计、毕业设计或小型物联网项目的开发者参考。压缩包共30个文件,以Keil工程源码(.c)、启动文件、项目配置文件(.uvproj)、编译中间产物(.lst、.obj)及可直接烧录的hex文件为主,整体仅47KB,发送端与接收端程序分目录存放,文件命名清晰,便于按需检索。已有948人在CSDN学习下载,属于容量精简但内容完整的实战型资源。资源同时给出发送端与接收端两套C语言代码,覆盖SCON、SBUF、TMOD等串口关键寄存器配置、SPI四线读写时序、LoRa工作频率与扩频因子设置、CRC错误检测、发送完成标志判断及接收中断处理等核心环节,可帮助读者从硬件接线到数据收发建立完整认知。代码结构简洁、注释清晰,可直接编译烧录,也适合初学者对照研究并快速移植到自己的项目中;配合串口调试助手使用,还能直观验证发送端与接收端之间的无线通信效果。
1. 51单片机通过LoRa实现远程通信:一看就懂的点对点无线链路怎么做
很多做嵌入式开发的朋友都有这种经历:项目做到一半,需求方突然说“数据不能只在本地看,得传到几百米外”。Wi-Fi覆盖不到室外,蓝牙传不远,4G模块又嫌成本高、功耗大。这时候 LoRa 几乎是唯一不用纠结的选择——51单片机搭配一个LoRa透传模块,用最朴素的串口发数据,就能把传感器读数送到一两公里外的接收端,中间不需要路由器、不需要SIM卡、不用交流量费。本文要讲的就是这条链路怎么从零搭起来:硬件怎么选、参数怎么配、协议怎么定、哪些地方最容易翻车。
这套方案特别适合三类人:学校实验室里做创新项目的学生,工厂里做设备状态监测的工程师,以及想用手头51单片机快速验证无线通信原理的爱好者。它不涉及复杂的射频知识,也不需要改PCB打板,两块开发板、两个模块、几根杜邦线就能跑起来。接下来我会按自己做过的方案来讲,从选型接线一直讲到收发代码和避坑经验,每一步都给可复现的细节。
2. 硬件选型和接线:51单片机配LoRa模块的三种组合方式
2.1 51单片机为什么还能打:成本、生态和教学场景
有人会觉得奇怪,都什么年代了还用51单片机做远程通信。但从项目落地角度看,51系列至今仍有不可替代的位置:某宝上一片STC89C52RC散片不到三块钱,开发板套件几十块还带下载器和各种外设例程,学校实验室里存量极大。更重要的是,51的GPIO操作和中断逻辑足够简单,用IO口模拟SPI时序去驱动LoRa模块,反而能让人把通信协议看得更清楚——相比直接拿着带硬件SPI的STM32调库,这种方式虽然笨,但每一步都在自己掌控中。
我一般会建议用STC89C52RC或者STC12系列,原因有两个:一是5V供电和3.3V的LoRa模块之间只做电平转换即可,不需要额外降压电路;二是STC的下载方式简单,一根USB转TTL线就能烧录,不用额外买调试器。如果项目对功耗有严格要求,可以考虑STC15系列的低功耗模式,但逻辑和代码结构基本不变。
2.2 LoRa模块选型:透传模块还是纯射频芯片
LoRa模块市面上大致分两类。一类是集成好固件的透传模块,比如常见型号的SX1278串口透传模块,你只管往串口丢数据,模块自己完成组包、发送、应答、重传,使用体验和蓝牙串口模块几乎一样。另一类是纯射频芯片方案,比如SX1278或者RA-02模块搭配单片机的SPI接口自己写驱动,寄存器配置、FIFO读写、中断处理全都要自己管。
对51单片机来说,我的建议是:第一次做选透传模块,先把链路打通;等原理清楚、项目需要自定义协议时,再换成SPI直驱方案。透传模块的典型接线就四根线:VCC、GND、TXD、RXD,外加一对配置引脚用来设置模块地址、信道和空中速率。这种方案调试周期短,半天就能出效果,特别适合验证性项目和教学场景。SPI方案则适合对数据格式有特殊要求、需要低延迟或者精确控制发射时机的场景,代价是代码量会从几十行涨到几百行。
2.3 电平转换和接线图:5V与3.3V之间的几种处理方式
51单片机输出高电平是5V,绝大多数LoRa模块的串口和SPI引脚是3.3V电平,直接接虽然短时间内不一定烧,但长期运行或者模块引脚没有做钳位保护时,风险很大。常见做法是串电阻分压——发送方向上串一个1K电阻把5V降到3.3V附近,接收方向则可以直接接,因为模块输出的3.3V高电平对51来说已经足够识别为高。这个方法省钱但波形边沿会变缓,通信速率高了以后容易出错。
更可靠的做法是用电平转换芯片,比如TXS0108E这类双向电平转换器,模块板载的AMC1117-3.3降压电路给模块供电,信号线经过转换芯片再接51。实际项目里我一般优先用转换芯片方案,尤其是需要跑超过9600波特率的串口通信时,波形质量直接影响误码率。还有一个容易被忽略的点是共地——LoRa模块的地和51开发板的地必须连在一起,否则串口电平没有参考基准,通信必然失败。
2.4 天线和供电的硬件细节:距离不够时先查这两个地方
LoRa模块的通信距离很大程度上取决于天线。模块标配的弹簧天线在开阔环境下能用,但一旦放进金属外壳、或者靠近地面,距离会急剧缩水。我见过一个项目,用户反馈说通信距离只有几十米,上门排查后发现是天线被压在PCB底下、旁边就是金属螺丝柱。换成外置SMA胶棒天线并把天线引出到机壳外部后,距离立刻恢复到几百米。
供电方面要注意LoRa发射瞬间的电流尖峰。SX1278在20dBm发射时峰值电流能到120mA左右,如果模块和单片机共用一条细杜邦线供电,压降会导致模块复位或者发射功率下降。建议用至少22AWG的导线给模块单独供电,或者直接在模块电源引脚旁边并一个100uF电解电容和一个0.1uF陶瓷电容做去耦,电容尽量靠近模块引脚放置。
3. 透传模式下的最小通信系统:串口配置与AT指令
3.1 透传模块的工作模式怎么设:地址、信道、速率三要素
透传模块的核心参数就三组:模块地址、信道(频率)、空中速率。两组模块要通信,地址和信道必须一致,空中速率也需要匹配。这里最容易踩坑的是“空中速率”和“串口波特率”的关系——它们不是同一个东西。串口波特率是51单片机和模块之间的通信速率,空中速率是模块与模块之间的射频通信速率。很多新手把两者混为一谈,结果空中速率设得太高,距离变短;设得太低,传输延迟变大。
以常见的E系列透传模块为例,配置指令通常是AT指令格式。模块进入配置模式后,通过串口发送AT+ADDR=xxxx设置地址,AT+CH=xxx设置信道,AT+AIR=xxx设置空中速率。配置完成后退出配置模式并重新上电,模块就按新参数工作。信道选择的依据是当地无线电管理规定,常用频段在410MHz到493MHz之间,这个范围内不同信道对应的具体频率可以查模块手册。
3.2 51单片机与透传模块的串口通信代码:发送端最小实现
有了透传模块,51单片机这边的工作就变得很轻松——不需要理解射频参数,只需通过串口把要发送的数据丢给模块。下面是最小化的发送端代码,我用的是常规STC89C52RC,晶振11.0592MHz,串口波特率9600。
#include <reg52.h> #define BUF_LEN 32 unsigned char tx_buf[BUF_LEN]; // 待发送数据缓冲区 // 串口1初始化:9600bps, 8N1 void UART_Init(void) { SCON = 0x50; // 串口模式1,允许接收 TMOD &= 0x0F; // 定时器1工作在模式2(8位自动重装) TMOD |= 0x20; TH1 = 0xFD; // 9600bps重装值(11.0592MHz晶振) TL1 = 0xFD; TR1 = 1; // 启动定时器1 ES = 1; // 开启串口中断 EA = 1; // 开启总中断 } // 发送单字节,阻塞等待发送完成 void UART_SendByte(unsigned char dat) { SBUF = dat; while (!TI); TI = 0; } // 发送一帧数据 void UART_SendFrame(unsigned char *buf, unsigned char len) { unsigned char i; for (i = 0; i < len; i++) { UART_SendByte(buf[i]); } } void main(void) { unsigned char count = 0; UART_Init(); while (1) { tx_buf[0] = 0xAA; // 帧头 tx_buf[1] = count++; // 数据:递增计数 tx_buf[2] = 0x55; // 帧尾 UART_SendFrame(tx_buf, 3); delay_ms(1000); // 每秒发送一次 } }这段代码的逻辑很直接:初始化串口后,每秒钟向LoRa模块发送一帧三字节的数据。TH1 = 0xFD是9600波特率的重装值,这个数值只适用于11.0592MHz晶振——如果换了晶振频率,这个值必须重新计算。透传模块收到数据后会自动加无线协议头、计算校验、按指定的空中速率发射出去,对单片机来说完全透明。
3.3 接收端代码与数据校验:别只读不看
接收端的代码比发送端稍微复杂一点,因为要处理数据什么时候到、数据是否完整的问题。用串口中断接收是比较自然的做法,每收到一个字节就存进缓冲区,然后根据帧头和帧尾判断是否收到完整的一帧。
#include <reg52.h> #define BUF_LEN 32 unsigned char rx_buf[BUF_LEN]; // 接收缓冲区 unsigned char rx_index = 0; bit frame_ready = 0; // 完整帧标志 // 串口中断服务函数 void UART_Isr(void) interrupt 4 { unsigned char dat; if (RI) { RI = 0; dat = SBUF; // 帧头判断:不是0xAA则丢弃,重新开始计数 if (rx_index == 0 && dat != 0xAA) { return; } rx_buf[rx_index++] = dat; // 帧尾判断:收到0x55且长度为3,说明一帧到齐 if (rx_index == 3 && dat == 0x55) { frame_ready = 1; rx_index = 0; } // 防溢出保护:缓冲区超限则重置 if (rx_index >= BUF_LEN) { rx_index = 0; } } } void main(void) { unsigned char i; UART_Init(); while (1) { if (frame_ready) { frame_ready = 0; // 此处处理收到的数据,例如从rx_buf[1]取出计数值 for (i = 0; i < 3; i++) { // 业务处理:可以是点亮LED、驱动蜂鸣器、转发到LCD等 P2 = rx_buf[1]; // 示例:把收到的数据送到P2口做显示 } } } }接收端要注意一个细节:LoRa透传模块从收到射频数据到从串口吐出来,中间有几十毫秒的延迟,所以单片机的中断接收逻辑不能假设数据会连续不间断到达——可能在收到帧头后,帧尾要过一会儿才来。上面的代码每次中断只处理一个字节,状态通过rx_index保存,这样即使帧间隔拉长也不会丢状态。
3.4 透传方案的边界和局限:什么时候该换SPI直驱
透传方案跑通后要清楚它的边界在哪里。第一是吞吐量受限,常见透传模块的空中速率最高也就19.2kbps左右,扣除协议开销,实际有效数据速率更低,不适合传图片、音频这类大数据。第二是延迟不确定,模块内部的组包和重传机制会让单次传输延迟在几十到几百毫秒之间波动,对实时性要求高的控制类应用不适用。第三是灵活性不足,你没法自定义帧格式、没法精确控制发射时刻、没法读取信号强度RSSI。
当项目开始需要以上这些能力时,就该考虑把透传模块换成SPI直驱的纯射频方案了。这也是下一章要展开的内容——用51的GPIO模拟SPI时序,直接操作SX1278的寄存器,从底层掌握通信链路的每个细节。
4. 上升级路线:51的IO口模拟SPI驱动SX1278
4.1 为什么51用IO模拟SPI可行:速率够用且代码可控
SX1278的SPI最高时钟频率是10MHz,但实际通信中我们通常只用1MHz以内。51单片机用IO口模拟SPI,得益于STC系列单片机的机器周期比传统51快很多——STC89C52RC在12T模式下主频12MHz,一条IO翻转指令大约耗时1us;而STC12系列在1T模式下可以达到接近1MHz以上的翻转频率,模拟2MHz以下的SPI完全没有压力。LoRa的配置操作本来就是低频的寄存器读写,不是高速连续数据流,所以IO模拟足够用。
选择IO模拟SPI还有一个好处:完全绕开51单片机的硬件SPI资源限制。传统51芯片大多没有SPI外设,就算有也需要和ISP下载共用引脚,项目代码写起来顾虑很多。IO模拟则可以把任意四个GPIO定义为SCK、MOSI、MISO、CS,布局走线灵活,代码逻辑直白,出了问题可以直接用示波器量引脚波形来排查。
4.2 SX1278关键寄存器配置:频率、SF、带宽、功率
SX1278的配置核心是LoRa调制参数。要设置的内容包括载波频率(Fr)、扩频因子(SF)、信号带宽(BW)、编码率(CR)、发射功率(Pa)、以及FIFO和中断的配置。下面是用IO模拟SPI方式初始化SX1278的代码框架,寄存器地址我直接写在注释里,方便对照芯片手册查阅。
#include <reg52.h> // SPI引脚定义,按实际接线修改 sbit SX_SCK = P1^0; sbit SX_MOSI = P1^1; sbit SX_MISO = P1^2; sbit SX_CS = P1^3; sbit SX_RST = P1^4; // 常用寄存器地址(SX1278) #define REG_FIFO 0x00 #define REG_OPMODE 0x01 #define REG_FRF_MSB 0x06 #define REG_FRF_MID 0x07 #define REG_FRF_LSB 0x08 #define REG_PA_CONFIG 0x09 #define REG_LNA 0x0C #define REG_MODEM_CONFIG1 0x1D #define REG_MODEM_CONFIG2 0x1E #define REG_PAYLOAD_LENGTH 0x22 #define REG_IRQ_FLAGS 0x12 // SPI写单个寄存器 void SX_WriteReg(unsigned char addr, unsigned char value) { unsigned char i; SX_CS = 0; // 写命令:地址最高位为0 for (i = 0; i < 8; i++) { SX_SCK = 0; SX_MOSI = (addr & 0x80) ? 1 : 0; addr <<= 1; SX_SCK = 1; } // 写数据:8位 for (i = 0; i < 8; i++) { SX_SCK = 0; SX_MOSI = (value & 0x80) ? 1 : 0; value <<= 1; SX_SCK = 1; } SX_CS = 1; } // SPI读单个寄存器 unsigned char SX_ReadReg(unsigned char addr) { unsigned char i; unsigned char value = 0; SX_CS = 0; // 读命令:地址最高位为1 for (i = 0; i < 8; i++) { SX_SCK = 0; SX_MOSI = (addr & 0x80) ? 1 : 0; addr <<= 1; SX_SCK = 1; } // 读数据 for (i = 0; i < 8; i++) { SX_SCK = 0; SX_SCK = 1; value <<= 1; if (SX_MISO) value |= 0x01; } SX_CS = 1; return value; } // SX1278初始化:433MHz,SF7,BW125kHz void SX_Init(void) { // 复位 SX_RST = 0; delay_ms(10); SX_RST = 1; delay_ms(10); // 进入睡眠模式,然后切到LoRa模式 SX_WriteReg(REG_OPMODE, 0x00); // 睡眠 SX_WriteReg(REG_OPMODE, 0x80); // LoRa模式 // 设置频率433MHz:FRF = 433MHz / FSTEP,FSTEP=61.035Hz // 因此寄存器值约为 433000000 / 61.035 ≈ 7093788 = 0x6C4000 SX_WriteReg(REG_FRF_MSB, 0x6C); SX_WriteReg(REG_FRF_MID, 0x40); SX_WriteReg(REG_FRF_LSB, 0x00); // 配置调制参数:SF7,BW125kHz,CR4/5 // RegModemConfig1 bit2-0是带宽;bit7-4是编码率;bit3-0是扩频因子(高1位在config2的bit7) SX_WriteReg(REG_MODEM_CONFIG1, 0x72); // BW=125kHz, CR=4/5, 低3位保留 SX_WriteReg(REG_MODEM_CONFIG2, 0x74); // SF=7, 开启CRC // 发射功率:20dBm SX_WriteReg(REG_PA_CONFIG, 0xFF); // 设置LNA增益 SX_WriteReg(REG_LNA, 0x23); // 设置单次发送长度 SX_WriteReg(REG_PAYLOAD_LENGTH, 8); }这段代码把SX1278配置到了433MHz、扩频因子7、带宽125kHz、编码率4/5的工作状态。REG_FRF_*三个寄存器组合起来设定载波频率,计算公式是频率除以步进61.035Hz后取整,再把结果拆成三个字节写入。REG_MODEM_CONFIG1和REG_MODEM_CONFIG2的值需要根据芯片手册的位定义仔细核算——这两处写错了最典型的症状是收发双方都配置了同样的参数但就是不通。
4.3 发射和接收流程:从写FIFO到中断标志轮询
SX1278收发数据走内部FIFO。发送时先把数据写入FIFO寄存器,然后设置发送模式并等待发送完成中断;接收时切换到接收模式,轮询或等待接收完成中断后从FIFO读取数据。下面给出发送一帧数据和接收一帧数据的最小代码。
// 发送一帧数据,len不超过255 void SX_SendPacket(unsigned char *data, unsigned char len) { unsigned char i; // 切换到待机模式 SX_WriteReg(REG_OPMODE, 0x81); // LoRa + Standby // 清空FIFO SX_WriteReg(REG_IRQ_FLAGS, 0xFF); // 写1清除所有中断标志 // 写入数据到FIFO for (i = 0; i < len; i++) { SX_WriteReg(REG_FIFO, data[i]); } // 设置负载长度 SX_WriteReg(REG_PAYLOAD_LENGTH, len); // 切换到发送模式 SX_WriteReg(REG_OPMODE, 0x83); // LoRa + TX // 等待发送完成(轮询,可优化为外部中断) while ((SX_ReadReg(REG_IRQ_FLAGS) & 0x08) == 0); // 清除完成标志,回到待机 SX_WriteReg(REG_IRQ_FLAGS, 0xFF); SX_WriteReg(REG_OPMODE, 0x81); } // 接收一帧数据,返回0表示无数据,1表示收到 bit SX_ReceivePacket(unsigned char *buf, unsigned char *len) { unsigned char flags; unsigned char i; unsigned char cnt; // 切换到接收模式 SX_WriteReg(REG_OPMODE, 0x85); // LoRa + RXCONT // 检查是否有接收完成中断 flags = SX_ReadReg(REG_IRQ_FLAGS); if ((flags & 0x40) == 0) { return 0; // 无数据 } // 读取实际接收到的字节数 cnt = SX_ReadReg(0x13); // RegRxNbBytes if (cnt > 0) { for (i = 0; i < cnt; i++) { buf[i] = SX_ReadReg(REG_FIFO); // 从FIFO读一个字节 } *len = cnt; } // 清中断标志 SX_WriteReg(REG_IRQ_FLAGS, 0xFF); return 1; }发射函数的核心是按照“待机→写FIFO→设置长度→切发射→查标志→回待机”的顺序操作,其中等待发送完成的轮询循环要注意加超时保护——如果天线脱落或者对方不在接收范围内,发送完成标志可能一直不置位,程序会卡死在循环里。接收函数的轮询方式简单但会占满CPU,实际项目里一般会利用SX1278的DIO0引脚接51的外部中断,在中断里处理收包,这样主循环可以去干别的活。
4.4 参数组合对距离和速率的影响:先理解再动手
SX1278最值得花的功夫是理解扩频因子、带宽和编码率三者的关系。扩频因子越高,接收灵敏度越好、通信距离越远,但空中传输速率越低——SF7速率约为SF12的6倍多。带宽越大,速率越快,但灵敏度下降,抗干扰能力变差。编码率冗余越多,抗干扰越强,但有效载荷占比变小。
实测项目中常用的几组参数我已整理在下面,覆盖了从近距离高速度到远距离低速率的典型场景。
| 场景描述 | 频率(MHz) | 扩频因子 | 带宽(kHz) | 编码率 | 空中速率(kbps) | 空旷距离参考 |
|---|---|---|---|---|---|---|
| 近距离高吞吐 | 433 | SF7 | 250 | 4/5 | 约11 | 200-500米 |
| 常规平衡配置 | 433 | SF7 | 125 | 4/5 | 约5.5 | 500米-1公里 |
| 远距离优先 | 433 | SF12 | 125 | 4/8 | 约0.3 | 2公里以上 |
| 抗干扰配置 | 470 | SF10 | 62.5 | 4/8 | 约0.7 | 受环境影响大 |
注意:参考距离是开阔地带、模块天线高于地面1.5米的实测结果。装在金属机箱里、天线横放、周围有建筑物遮挡,距离都会成倍缩水。如果测试距离和表中差距过大,优先检查天线和供电,而不是反复调参数。
5. 51单片机LoRa通信的5个典型避坑记录
5.1 串口打印乱码:波特率不是你以为的那个
现象:接收端串口助手显示的字符完全不可读,一堆乱码符号。原因:发送端51单片机的晶振是11.0592MHz,代码里按9600算的初值;但实际板子上焊的是12MHz晶振——两者算出的波特率误差前者为零,后者高达3.5%以上,串口通信直接失效。解决:先确认板子晶振频率;11.0592MHz晶振配9600,12MHz晶振建议改用4800或者换用STC的定时器自动重装模式去匹配。检查方法很简单,用示波器量一下TXD引脚的波形宽度,理论上9600波特率的一位是104us,偏差超过5%就需要调晶振或换波特率。
5.2 LoRa模块收不到数据但发送端明明在发
现象:发送端代码跑得好好的,串口也确认数据已经从51发出,但接收端毫无反应。原因:收发双方的LoRa参数不一致,比如发送端SF7、接收端SF8。透传模块情况下,可能是地址或信道不匹配;SPI方案下,是初始化代码里寄存器配置不一致。解决:先用最简单的固定参数测试——收发双方都停在SF7、125kHz、433MHz这三项上,确认通了再调整。另外,发射端天线没接、接收端天线接触不良也会导致信号出不去或者进不来,换个天线试试就能排除。
5.3 天线和外壳导致距离骤降
现象:裸板测试距离几百米没问题,装进塑料外壳后距离缩到几十米,偶尔还不通。原因:天线贴着PCB走线或者被外壳内部的金属件遮挡,等效辐射效率大幅下降。解决:天线必须悬空或伸出外壳,且周围至少5mm内不要有金属物体;如果外壳是金属的,必须使用外置吸盘天线并打孔引出。还有一个常见错误是用了SMA转接延长线但线材质量差,线损过大同样会吃掉功率。
5.4 发送后程序卡死,LoRa模块发热严重
现象:发送函数运行后程序不往下走,模块表面烫手。原因:没有配置正确的PA引脚——SX1278的20dBm发射需要把PA_BOOST引脚通过电感接到RF端口,如果电路设计里用的是普通RFIO引脚,而代码里按PA_BOOST模式配置了最大功率,模块会进入异常工作状态。解决:检查硬件原理图,确认模块是否引出了PA_BOOST引脚。多数成品模块默认走PA_BOOST路径,但自己画的板子容易忽略这个细节。代码里的REG_PA_CONFIG值需要根据实际电路选0xFF(PA_BOOST最大功率)还是0x09(普通输出)——选错了轻则距离大减,重则模块损坏。
5.5 距离测试结果好坏全靠运气:测试方法不标准化
现象:今天测了500米能通,明天同样的环境和设备只有100米,开始怀疑模块质量。原因:测试方法不一致——人的位置、模块高度、天线朝向、甚至测试时段都会影响结果。LoRa信号受地面反射和多径效应影响,模块离地10厘米和离地1.5米,距离差距可能达到一个数量级。解决:建立固定的测试流程——接收端固定位置、天线垂直朝上、离地至少1.5米;发送端也是同样的摆放姿态;在每个距离点至少连续发送50帧,统计丢包率而不是只看“偶尔收到一帧”。这样才能客观评估方案的实际覆盖能力。
6. 进阶验证技巧:用RSSI校准天线位置和参数组合
当你已经能把数据从A点传到B点,下一步值得做的事情是校准——不是盲目加大功率,而是利用SX1278提供的RSSI(接收信号强度指示)寄存器,精确地知道每一处的信号余量,从而判断天线摆放和参数组合是否合理。RSSI寄存器是0x1A和0x1B两个字节,上一个存信号强度的整数值,下一个存小数值,计算公式是RSSI(dBm) = -137 + 整数部分 + 小数部分/256,单位是dBm。我通常会在接收数据的同时读取这两个寄存器,在串口助手里把RSSI值打出来,就能看到每个位置的信号电平。
具体的用法是:固定发送端,拿着接收端在不同位置测RSSI。如果空旷地带RSSI在-60dBm以上,说明链路质量很好;-80dBm左右是正常水平;低于-100dBm就要注意了,这个位置已经接近灵敏度极限,随时可能丢包。这时候如果天线朝向调整一下能带来3-5dBm的改善,说明当前摆放有问题。如果无论怎么调整都在-100以下,就要考虑换SF12或者把接收端位置抬高。
同样的方法也能用来验证参数组合:把发送端的SF从7改到12,在同一个位置观察RSSI的变化——通常SF12能带来约5dBm的灵敏度提升,而这个提升有时比增大发射功率更明显。我在一个模拟项目X中就是用这个方法,把原来SF7、天线贴地的组合从80米通信距离提升到600米以上——只调整了天线姿态和SF,没有换任何硬件。
这套流程操作简单:在接收代码里加几行读取RSSI、通过串口上报的逻辑。51单片机做这件事没有额外硬件成本,数据本身就有RF底层信息,比买频谱仪实测便宜太多。我个人的习惯是每次部署前都先做一轮RSSI扫描,把链路余量做到20dBm以上再交付,这样后续维护很少收到“又不通了”的反馈。说到底,LoRa通信链路的大多数问题都不是芯片不行,而是天线的物理位置和参数配置没校准。如果你做完这套方案也遇到距离不理想的情况,建议先不要怀疑模块,按这个思路去排查天线的真实状态,希望帮到你。
本文还有配套的精品资源,点击获取