简介:面向物联网无线通信开发者与专利研究者的发明专利文档,聚焦LoRa无线模块在CAD(空闲信道评估)模式下的嗅探方法与系统实现。方案围绕两个模块的交互展开:一方以CAD检测模式循环发射射频参数序列帧,另一方在嗅探状态下发送CAD嗅探帧,在仅知对方射频参数范围的前提下逐步匹配参数、返回信标帧并建立数据通讯;文中还给出唤醒时刻窗口内的探测帧时序约束等判定条件,用以缩短唤醒时间、降低设备功耗。包内为1个PDF文件,约777KB,即该专利的申请公布文本,含权利要求书4页、说明书10页、附图4页,可把握技术框架与权利要求范围。已有261人学习,读者可获得LoRa CAD嗅探的完整技术路线、参数序列匹配与状态机切换细节,以及低功耗唤醒设计思路,适合智能传感、远程监控等场景研发与专利检索参考。
1. LoRa 模块的 CAD 模式为什么值得单独做一套嗅探方法
LoRa 无线模块的 CAD 模式,是这套嗅探方法里最容易被忽略的一半:它不是解码器,只是芯片内部一个几毫秒就给出结论的前导码相关器。把它当成嗅探器的“门铃”,门铃响了再开接收机,一套只被动听、不发射的 LoRa 嗅探系统就能用一节小电池在野外蹲上几周——这正是“基于 LoRa 无线模块 CAD 模式的嗅探方法及系统”要解决的现实问题。它适合两类人:一类要给私有 LoRa 网络做现场勘测,想知道某个点位到底有没有信号、信号从哪个方向来;另一类要在不改动现网设备的前提下,做长期的链路占用率和空口质量统计。往下按“机理—单机跑通—多机成系统—踩过的坑—把指标压到可验证”的顺序拆。
2. CAD 的检测机理:几毫秒里它到底比对了什么
很多人第一次看手册会把 CAD 理解成“测一下信道能量”,然后在现场发现它对着噪声也能报检出,就断定这颗芯片不可靠。翻车的根源在于把 CAD 当成 RSSI 门限用了。它内部是两段判断,第二段是真正的相关运算,参数对不上就是永远不触发,参数对上了才谈灵敏度和误报。
2.1 先量噪声本底,再做前导码相关
SX127x 收到 CAD 指令后,先采一次 RSSI 确定当前信道的噪声本底,然后把解调器切到相关模式,把空中收到的信号和芯片内部已知的 up-chirp 前导码做匹配。相关峰相对本底的比值超过RegDetectThreshold设定的门限,才置位 CadDetected。所以它回答的问题只有一个:现在信道上有没有一个参数匹配的 LoRa 前导码正在经过。
这一条决定了整套方法的边界——CAD 只能当触发器,不能当接收机。真正的包还得靠切到 RX 之后由调制解调器自己同步、解调、校验 CRC。任何把顺序搞反的实现,比如指望 CAD 直接给出数据或者用 CadDetected 当作“收到一帧”,都会在第一次联调时卡住。相关的只有前导码,前导码之后是显式报头还是隐式报头、编码率多少、payload 多长,CAD 一概不知。
2.2 CadDone 与 CadDetected 两个标志位撑起整个状态机
一次完整的 CAD 探测只有四个状态:空闲、检测中、检出、未检出。芯片用 CadDone 表示“这轮比完了”,用 CadDetected 表示“比上了”。两者是独立的两根标志位,正常时序是 CadDone 置位时 CadDetected 已经就绪,可以一次性读回;只读一次就把两个位都取出来,是这个状态机最容易写错的地方,后面第 5 章会专门讲。
判断顺序必须是先等 CadDone,再看 CadDetected。反过来写会在检测还没结束时读到上一轮的残留标志,表现为“偶尔凭空多出一帧”。另外 CAD 一定要有超时兜底,SF12 配合 500kHz 带宽和异常干扰时,单轮耗时能顶到几十毫秒,超时值按最大 SF 的窗口往上留 20% 就够了。
2.3 算一笔电流账:为什么值得为 CAD 写一堆状态机
常开接收是这套系统最贵的部分。SX127x 在 BW125kHz 下的接收电流典型值在 10~12mA 量级,一颗 2000mAh 的电池撑不到一周。CAD 窗口内的电流和接收差不多,但窗口本身很短,真正决定平均电流的是占空比。
| 工作状态 | 电流量级 | 说明 |
|---|---|---|
| 连续接收 RXCONT | 10~12 mA | 一直在听,MCU 也得常醒 |
| CAD 窗口内 | 10~12 mA | 只持续 T_cad,毫秒级 |
| 单次接收 RXSINGLE | 10~12 mA | 只在检出后开,等一帧的时间 |
| 休眠(寄存器保持) | 1~2 µA | 配置不掉,唤醒即用 |
| MCU 深度睡眠 | 视平台 | 主频降下来才不拖后腿 |
拿 SF9/BW125 举例:CAD 窗口按经验公式 T_cad ≈ (2^SF + 32)/BW 估算约 4.3ms;目标网络用默认 8 个前导码符号,空中时长 8×512/125000 ≈ 32.8ms,轮询周期取 35ms 才能不漏;占空比 4.3/35 ≈ 12%,平均电流约 11mA×0.12 ≈ 1.3mA,比常开接收省约 8 倍。如果把目标网络的前导码改成 16 个符号(65.5ms),轮询周期可以放到 70ms,占空比降到 6%,平均电流落到 0.7mA 上下——这就是把前导码长度当参数用的价值。
注意:上面的公式和电流是量级参考,不同批次芯片、不同 LNA 增益、不同供电电压都有偏差,正式定参数前要用实测表替换,方法见第 6 章。
2.4 SX127x 和 SX126x 的差别:谁来承担“检出到收包”的那段空窗
SX127x 的 CAD 结束后芯片回到待机,必须由 MCU 通过 SPI 写 OpMode 切到单次接收。这段空窗包括 SPI 事务、函数调用、可能还有一次 RTOS 调度,几十微秒到几毫秒不等。SF7 的前导码只有 8.2ms,勉强够用;如果目标网络把前导码压到 4 个符号,SF7 下只剩 4.1ms,中断加调度的延迟就足以把同步字整段错过去。
SX126x 把这件事做进了硬件:SetCadParams里有个cadExitMode,配成 CAD_RX 时芯片在检出后自动进接收并保持到cadTimeout到期,MCU 只在 RxDone 时才被叫醒。同一个cadSymbolNum参数还能把相关窗口从 1 个符号拉到 16 个符号,窗口越长越灵敏、越费电。做这类长期蹲守的系统,我一般优先选带硬件自动切换的型号,能省掉一整类时序 bug。
3. 把 CAD 嗅探跑起来:从清标志到读出 FIFO 的最小闭环
原理清楚之后,第一块板子要验证的事情很有限:能不能在目标信道触发 CadDetected,触发之后能不能把那一帧完整读出来。这一步跑通,后面的多节点和调度才有意义。
3.1 频率、带宽、扩频因子、同步字四件套必须先对齐
CAD 的相关器只认和自己配置一致的 chirp。频率偏 100kHz、带宽从 125 写成 250、SF 差一档,表现出来的现象都是“CadDetected 从来不置位”,很容易被误判成硬件坏了。
| 参数 | 取值来源 | 配错的典型现象 |
|---|---|---|
| 中心频率 | 被测网络频点 | 完全不触发,或只在极近场触发 |
| 带宽 BW | 125/250/500 kHz | 相关峰对不上,检出率接近 0 |
| 扩频因子 SF | 7~12 | 同上,且收包必然 CRC 错 |
| 同步字 | 公网 0x34,私有网常改 | CAD 能触发,收包永远失败 |
| 前导码长度 | 目标网络配置 | 不改也能收,但捕获率被轮询周期限制 |
| 编码率 CR | 目标网络配置 | 只影响解调,CAD 阶段不敏感 |
表里同步字这一行是最阴的:前导码是固定的 chirp 序列,不含同步字信息,所以 CAD 照样能触发,你会看到检出率漂亮得不行,但一帧都收不下来。第一次联调如果遇到“CAD 一直报检出、RX 一直超时”,先怀疑同步字,别怀疑天线。
3.2 一次完整探测的代码:清标志、等 CadDone、切接收、读 FIFO
/* cad_sniff.c —— 单通道 CAD 嗅探最小闭环(SX127x 寄存器级) */ #include <stdint.h> #include <stdbool.h> /* 平台层:spi_rw 写入时忽略返回值,读取时 val 传 0x00 */ extern uint8_t spi_rw(uint8_t addr, uint8_t val); extern uint32_t now_us(void); extern void radio_idle(void); /* 切 STDBY,改配置前必须先调 */ #define R_FIFO 0x00 #define R_OPMODE 0x01 #define R_FRFMSB 0x06 #define R_FRFMID 0x07 #define R_FRFLSB 0x08 #define R_MC1 0x1D #define R_MC2 0x1E #define R_PREAMBLELSB 0x21 #define R_SYNCWORD 0x39 #define R_DETECTOPT 0x31 /* 高 5 位为 DetectionOptimize */ #define R_DETTHRESH 0x37 /* 默认 0x0A,越小越灵敏 */ #define R_IRQFLAGS 0x12 /* 读后清零,务必只读一次 */ #define R_RXNB 0x13 #define R_FIFOCUR 0x10 #define R_FIFOPTR 0x0D #define R_PKTRSSI 0x1A #define R_PKTSNR 0x1B #define MODE_CAD 0x87 /* LoRa + CAD */ #define MODE_RXSINGLE 0x86 /* LoRa + 单次接收 */ #define IRQ_CADDETECTED 0x01 #define IRQ_CADDONE 0x04 #define IRQ_CRCERR 0x20 #define IRQ_RXDONE 0x40 #define IRQ_RXTIMEOUT 0x80 #define CAD_TIMEOUT_US 40000u /* 覆盖 SF12/BW125,按最大 SF 留余量 */ #define RX_TIMEOUT_US 3000000u /* 单帧上限,SF12 长包可能超 2s */ typedef enum { CAD_IDLE = 0, CAD_HIT = 1, CAD_TIMEOUT = -1, CAD_RX_FAIL = -2 } cad_result_t; typedef struct { uint8_t buf[64]; uint8_t len; int16_t rssi_dbm; int8_t snr_db; bool crc_ok; uint32_t t_hit_us; /* CadDetected 时刻,不是收完的时刻 */ } lora_frame_t; static void cfg_rx_chain(uint32_t freq_hz, uint8_t mc1, uint8_t mc2) { radio_idle(); uint32_t frf = (uint32_t)(((uint64_t)freq_hz << 19) / 32000000ULL); spi_rw(R_FRFMSB, (frf >> 16) & 0xFF); spi_rw(R_FRFMID, (frf >> 8) & 0xFF); spi_rw(R_FRFLSB, frf & 0xFF); spi_rw(R_MC1, mc1); /* 带宽 + 编码率 + 显式报头 */ spi_rw(R_MC2, mc2); /* SF + CRC 使能 */ spi_rw(R_PREAMBLELSB, 0x08); /* 只影响预期,不影响能否检出 */ spi_rw(R_SYNCWORD, 0x34 <p> <a href="https://download.csdn.net/download/ypp240124016/90055987" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>