3. LoRa 点对点链路参数配置与丢包率测试
链路预算与参数组合设计
LoRa 点对点链路能否在农田场景稳定工作,取决于四个可配置参数之间的耦合关系:频点决定合法频段与干扰环境,扩频因子 SF决定灵敏度与空中时间,带宽 BW决定速率与抗噪能力,发射功率决定链路余量但受法规与功耗约束。本案例选用 SX1278(433 MHz 频段)模块对,主控为 STM32,通过 SPI 配置寄存器,串口输出测试统计。
先明确参照约定:RSSI 以 dBm 表示,数值越接近 0 信号越强;SNR 以 dB 表示,负值表示信号低于噪声底但仍可解调(LoRa 特性)。丢包率定义为 (发送包数 − 接收包数) / 发送包数 × 100%,发送端每包携带递增序号,接收端按序号缺口统计。
参数组合设计原则:SF 每增加 1,灵敏度约改善 2.5 dB,但空中时间翻倍;BW 从 500 kHz 降到 125 kHz,灵敏度改善约 3 dB,速率降为 1/4;发射功率从 10 dBm 提到 17 dBm 仅增加 7 dB 余量,却显著增加功耗。因此测试矩阵应覆盖“低速率高灵敏”与“高速率低灵敏”两端,找出满足丢包率阈值的最低功耗组合。
寄存器级配置实现
SX1278 通过 SPI 访问寄存器。关键配置项:RegFrfMsb/Mid/Lsb 设置频点(FrF = f × 2²⁴ / 32 MHz),RegModemConfig1 设置 BW 与编码率,RegModemConfig2 设置 SF,RegPaConfig 设置功率。以下为发送端核心初始化与发包代码,接收端仅需将模式改为连续接收并读取 RegPktRssiValue 与 RegPktSnrValue。
#include "stm32f1xx_hal.h"
/* 频点 433.175 MHz → FrF = 433175000 * 2^24 / 32000000 = 0x6C8CCC */
#define FRF_MSB 0x6C
#define FRF_MID 0x8C
#define FRF_LSB 0xCC
/* 参数组合结构体 */
typedef struct {
uint8_t sf; /* 7~12 */
uint8_t bw; /* 0=125k, 1=250k, 2=500k */
uint8_t tx_dbm; /* 10/14/17 */
} lora_cfg_t;
static void lora_write(uint8_t addr, uint8_t val) {
uint8_t buf[2] = { addr | 0x80, val };
HAL_SPI_Transmit(&hspi1, buf, 2, 100);
}
static uint8_t lora_read(uint8_t addr) {
uint8_t tx = addr & 0x7F, rx;
HAL_SPI_Transmit(&hspi1, &tx, 1, 100);
HAL_SPI_Receive(&hspi1, &rx, 1, 100);
return rx;
}
void lora_init(const lora_cfg_t *c) {
/* 进入睡眠模式配置 */
lora_write(0x01, 0x80);
/* 频点 */
lora_write(0x06, FRF_MSB);
lora_write(0x07, FRF_MID);
lora_write(0x08, FRF_LSB);
/* ModemConfig1: BW[7:4] | CR[3:1] | 显式头[0] */
uint8_t bw_bits = (c->bw == 0) ? 0x70 : (c->bw == 1) ? 0x80 : 0x90;
lora_write(0x1D, bw_bits | 0x02); /* CR=4/5 */
/* ModemConfig2: SF[7:4] | CRC使能[2] */
lora_write(0x1E, ((c->sf) << 4) | 0x04);
/* 功率: PA_BOOST, 17dBm 时 0x8F; 14dBm 时 0x8E; 10dBm 时 0x8A */
uint8_t pa = (c->tx_dbm == 17) ? 0x8F : (c->tx_dbm == 14) ? 0x8E : 0x8A;
lora_write(0x09, pa);
/* 前导码长度 8 */
lora_write(0x20, 0x08);
/* 负载长度 */
lora_write(0x22, 0x08);
/* 进入待机 */
lora_write(0x01, 0x81);
}
void lora_send_packet(uint8_t *data, uint8_t len) {
lora_write(0x0E, 0x80); /* FIFO 指针复位 */
lora_write(0x0D, 0x80); /* 映射 FIFO */
for (uint8_t i = 0; i < len; i++)
lora_write(0x00, data[i]);
lora_write(0x22, len);
lora_write(0x01, 0x83); /* TX 模式 */
while (!(lora_read(0x12) & 0x08)); /* 等待 TxDone */
lora_write(0x12, 0x08); /* 清标志 */
}
关键校验点:配置完成后读回 RegModemConfig1/2 确认写入值;用频谱仪或另一台已知配置的接收机确认频点偏差在 ±10 kHz 内。若 SF 与 BW 不匹配(如 SF12 + BW500),空中时间会显著缩短但灵敏度下降,需在测试矩阵中单独标注。
丢包率与 RSSI 统计方法
发送端每包负载为 8 字节:[序号高字节, 序号低字节, 0xAA, 0x55, 温度×10, 湿度, 电压, 校验]。接收端维护一个 16 位序号窗口,收到包后记录 RSSI、SNR 与序号,测试结束后按以下规则统计:
- 发送总数 N = 100(每组合),接收总数 M = 去重后有效序号数。
- 丢包率 = (N − M) / N × 100%。
- RSSI 取所有有效包的中位数,避免个别异常值干扰。
- SNR 取均值,若均值 < −15 dB 则标记为“解调临界”。
| 组合 | 场景 | SF | BW | TX | 丢包率 | RSSI 中位数 | SNR 均值 | 判定 |
|---|---|---|---|---|---|---|---|---|
| C1 | 视距 | 7 | 500 | 17 | 0% | −78 dBm | +9.5 dB | 可用 |
| C1 | 非视距 | 7 | 500 | 17 | 18% | −112 dBm | −6.2 dB | 不可用 |
| C2 | 视距 | 9 | 125 | 14 | 0% | −82 dBm | +7.8 dB | 可用 |
| C2 | 非视距 | 9 | 125 | 14 | 3% | −118 dBm | −11.4 dB | 可用 |
| C3 | 视距 | 12 | 125 | 10 | 0% | −85 dBm | +6.1 dB | 可用 |
| C3 | 非视距 | 12 | 125 | 10 | 1% | −124 dBm | −14.8 dB | 可用(临界) |
示例数据说明:上表为教学示例,用于演示判读方法,非实测结果。实际测试中 RSSI 受天线增益、馈线损耗、作物含水率影响,同一组合在不同地块可能相差 6~10 dB。建议每个场景至少重复 3 轮,取丢包率中位数作为判定依据。
参数确定与复测建议
根据判读逻辑,非视距场景下 C1(SF7/BW500)丢包率 18% 属于临界偏不可用,C2(SF9/BW125)丢包率 3% 且 RSSI −118 dBm 满足可用条件,C3(SF12/BW125)虽可用但空中时间 1.3 s 导致功耗与延迟偏高。因此推荐链路参数为 SF9 / BW125 / TX14 dBm,在保证非视距可靠性的同时兼顾功耗与实时性。
复测时建议:将 C2 组合在非视距场景下连续运行 30 分钟(900 包),确认丢包率稳定在 5% 以内;同时用万用表测量发送端平均电流,验证 14 dBm 相比 17 dBm 的功耗收益是否达到预期(典型差异约 20~30 mA 峰值电流)。若现场出现 RSSI 骤降超过 10 dB,优先排查天线接头进水或作物冠层增厚导致的额外衰减。