cpp
lr20xx_radio_lora_pkt_params_t radio_pkt_params =
{
.preamble_len_in_symb = 8,
.pkt_mode = LR20XX_RADIO_LORA_PKT_EXPLICIT,
.pld_len_in_bytes = 255,
.crc = true,
.iq = false
};
LoRa 空中包格式
一个 LoRa 包在空中的结构:
┌──────────────┬──────────┬──────────────┬───────┬─────────┐
│ Preamble │ Header │ Payload │ CRC │ │
│ (前导码) │ (可选) │ (载荷) │ (可选) │ │
│ │ │ │ │ │
│ 8~65535符号 │ 显式/隐式 │ 1~255字节 │ 2字节 │ │
└──────────────┴──────────┴──────────────┴───────┴─────────┘
←── 接收机用来检测和同步 ──→ ←── 真正要传的数据 ──→
每个参数对应一个部分:
preamble_len_in_symb = 8
前导码长度 ,单位是符号(不是字节)。
前导码就是一段持续上调频的信号:
频率
│ ┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐ ← 8 个 chirp 符号
│ ││││││││││││││││
│ ─┘└┘└┘└┘└┘└┘└┘└┘
└──────────────────────► 时间
←── preamble ──→
接收机靠这段信号:
1. 检测到"有包来了"
2. 同步时钟和频率偏移
3. 确定符号边界
| 值 | 效果 |
|---|---|
| 4~6 | 极短,适合高 SNR 环境,省空中时间 |
| 8 | demo 默认,平衡选择 |
| 12 | 较保守,弱信号下更可靠 |
| 65535 | 理论最大,实际不会用 |
建议:8 或 12,根据环境噪声调整。
pkt_mode = LR20XX_RADIO_LORA_PKT_EXPLICIT
包头模式:显式 vs 隐式
显式 (EXPLICIT): 隐式 (IMPLICIT):
┌──────┬────────┬──────┬─────┐ ┌──────┬────────┬─────┐
│Pream │Header │数据 │ CRC │ │Pream │ 数据 │ CRC │
│ │长度/CR │ │ │ │ │ │ │
└──────┴────────┴──────┴─────┘ └──────┴────────┴─────┘
Header 里告诉接收方: 没有 Header!
- 载荷有多少字节 收发双方必须提前约定好
- 用了什么 CR 载荷长度和 CR
- 有没有 CRC
| 模式 | 优点 | 缺点 |
|---|---|---|
| 显式 | 灵活,接收端自动知道包长 | 多占 ~2.5 符号的空中时间 |
| 隐式 | 包更短(快) | 收发双方必须固定参数,一改就对不上 |
pld_len_in_bytes = 255
载荷长度(字节)。这只是初始值,实际发送/接收前会被覆盖:
// 发送时动态改成实际长度
radio_pkt_params.pld_len_in_bytes = sizeof(tx_buffer);
lr20xx_radio_lora_set_packet_params(context, &radio_pkt_params);
| 模式 | pld_len 含义 |
|---|---|
| 显式 | Header 里告诉接收方,接收方自动适配 |
| 隐式 | 发送方和接收方必须设成一样的值,否则解码失败 |
crc = true
包尾 CRC 校验。
┌────────────┬─────────────────────────┬──────┐
│ Payload │ CRC16 (2字节) │ │
│ 你的数据 │ 0xA3F1 │ │
└────────────┴─────────────────────────┴──────┘
↑
接收方算一遍,和收到的比对
一致 = 包正确,不一致 = RP_STATUS_RX_CRC_ERROR
| 值 | 效果 |
|---|---|
| true | 多 2 字节开销,有错误检测 |
| false | 节省 2 字节,错误的包会悄悄通过 |
几乎不关。 有自己的 CRC 在应用层再算一遍,但物理层 CRC 仍然建议开着 --- 提前丢弃坏包。
iq = false
IQ 极性:是否反转。
LoRa 调制的数学本质是 chirp 信号 ------ 频率随时间线性增加(up-chirp)或减少(down-chirp)。IQ 反转意味着把 I 路和 Q 路互换,等效于翻转 chirp 方向。
正常 (iq=false): 反转 (iq=true):
频率 ↑ / / / / 频率 ↑ \ \ \ \
│/ / / / │\ \ \ \
└─────────► 时间 └─────────► 时间
上调频 chirp 下调频 chirp (等效)
收发双方必须一致。 不一致 = 物理层完全无法解调,表现为接收方什么也收不到。
| 协议 | iq 值 |
|---|---|
| LoRaWAN | false (0x34 同步字时) / true (0x12 同步字时) |
| 私有网络 | 典型 false |
cpp
/* LR2021 配置射频同步字参数 */
lr20xx_radio_lora_set_syncword(E80_CONTEXT, SYNC_WORD_NO_RADIO);
射频同步字:Sync Word --- 网络"身份证"
Sync Word --- 网络"身份证"
空中同一频率上:
┌────────────────────────────────────────────────┐
│ 868 MHz 信道上可能同时有: │
│ │
│ 设备A (sync=0x12) ──── PING ────► 设备B (0x12) │ ← 私有网络,互通
│ 设备C (sync=0x34) ──── DATA ────► 设备D (0x34) │ ← LoRaWAN,互通
│ │
│ 设备A (0x12) ──── PING ───X─── 设备D (0x34) │ ← sync 不同,互相
│ 设备C (0x34) ──── DATA ───X─── 设备B (0x12) │ 完全收不到对方
└────────────────────────────────────────────────┘
Sync Word 是 LoRa 包最前面的比特序列,接收机用它判断"这个信号是发给我的吗"。
0x12 → 私有网络 (和你用的 E80 demo `SYNC_WORD_NO_RADIO` = 0x34 不同)
0x34 → LoRaWAN 公有网络
收发双方必须一致。不一致 = 物理层直接丢弃,连 CRC 校验都到不了。
| 值 | 场景 |
|---|---|
0x12 |
私有网络,不和 LoRaWAN 设备互干扰 |
0x34 |
LoRaWAN 兼容,可以和 LoRaWAN 网关互通 |
| 自定义 0x00~0xFF | 自己定义,隔离不同网络 |
Modulation Params --- 物理层"三围"
lr20xx_radio_lora_mod_params_t mod_params =
{
.bw = LR20XX_RADIO_LORA_BW_125, // 带宽
.cr = LR20XX_RADIO_LORA_CR_4_5, // 编码率
.sf = LR20XX_RADIO_LORA_SF8, // 扩频因子
.ppm = LR20XX_RADIO_LORA_NO_PPM, // PPM 优化
};
sf --- Spreading Factor(扩频因子)
LoRa 最核心的参数。每个符号携带 2^SF 个 chirp 片。
SF7 (128 chirps/符号): SF12 (4096 chirps/符号):
│ / / / / / / │ ← 一个符号 │ / / / / / / / / / / / / / │
│ 符号很短 │ │ / / / / / / / / / / / / / │ ← 一个符号
│ 数据快 │ │ / / / / / / / / / / / / / │
│ 距离短 │ │ / / / / / / / / / / / / / │
│ │ │ 符号很长,数据慢,距离极远 │
└───────────────┘ └────────────────────────────┘
| SF | 符号时长 (BW125) | 比特率 (CR4/5) | 灵敏度 | 空中距离 |
|---|---|---|---|---|
| SF5 | 0.26 ms | 15.6 kbps | -117 dBm | 近 |
| SF7 | 1.0 ms | 5.5 kbps | -124 dBm | ↑ |
| SF8 | 2.0 ms | 3.1 kbps | -127 dBm | |
| SF9 | 4.1 ms | 1.8 kbps | -130 dBm | |
| SF10 | 8.2 ms | 976 bps | -133 dBm | |
| SF11 | 16.4 ms | 537 bps | -135 dBm | |
| SF12 | 32.8 ms | 293 bps | -137 dBm | 远 |
bw --- Bandwidth(带宽)
LoRa 信号占用的频谱宽度。BW 越大 → 符号越短 → 数据越快 → 但灵敏度略降。
cpp
BW=125kHz: BW=500kHz:
│ ┌──┐ │ │ ┌──┐ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ └──┘ │ │ └──┘ │
└──────┘ └──────┘
125kHz 500kHz
窄, 符号长 同一个 chirp 在更宽的
频率范围内展开,符号短4倍
| BW | 兼容性 |
|---|---|
| 125 kHz | 最常用,所有芯片支持 |
| 250 kHz | 常用 |
| 500 kHz | 常用,速度快 |
| 203 kHz | LR20xx 特有 |
| 812 kHz | LR20xx 特有 |
cr --- Coding Rate(编码率)
CR 就是 LoRa 的 FEC。 它是一个东西的两个名字 ------ CR 是 LoRa 的叫法,FEC 是通用术语。
在数据里插入冗余,接收端用来纠错。CR = 4/(4+N),N 越大冗余越多。
CR 4/5: 每 4bit 数据 + 1bit 冗余 → 效率 80%
CR 4/8: 每 4bit 数据 + 4bit 冗余 → 效率 50% (和重发一次一样)
实际空中数据: ┌──数据──┬─冗余─┐
CR 4/5 │████████│ ░░░░ │ 冗余少,速度快
CR 4/6 │████████│░░░░░░│ 平衡
CR 4/7 │████████│░░░░░░│░░│
CR 4/8 │████████│░░░░░░│░░░░░░│ 冗余多,抗干扰强
| CR | 编码效率 | 抗干扰 |
|---|---|---|
| 4/5 | 80% | 弱 |
| 4/6 | 67% | 中 |
| 4/7 | 57% | 强 |
| 4/8 | 50% | 最强 |
| LI_4/5~LI_4/8 | 同上 | Long Interleaver 抗突发干扰 |
ppm --- PPM Offset(低速率优化 / 频偏保护)
LR20XX_RADIO_LORA_NO_PPM = 0x00 // 不用,用全部调制范围
LR20XX_RADIO_LORA_PPM_1_4 = 0x01 // 每4个bin只用一个,抗频偏
低速率(高SF+窄BW)时,收发双方的晶振频偏可能导致 chirp 漂移到相邻 bin,ppm=1 能容忍更大的频偏。 高速率(SF5~SF7)用不到,选 NO_PPM。