这个需求切中了 LoRa 低功耗应用的核心痛点!STM32WL 开启 LoRa CAD(信道活动检测)的核心是通过配置 SubGHz 外设参数、注册中断回调与状态机,让设备仅在检测到匹配前导码时启动接收,否则进入低功耗,大幅降低电池供电设备的功耗。本文基于 LAT1294 应用笔记,拆解 CAD 原理、驱动支持与完整配置步骤,助力快速落地。
1. 核心概述
1.1 应用场景与价值
- 核心需求:电池供电的 LoRa 设备(如传感器、遥控器)需按需接收指令,避免持续接收导致高功耗;
- CAD 作用:检测信道上是否存在匹配扩频因子(SF)和频率的 LoRa 前导码,检测到则唤醒接收,否则休眠;
- 关键优势:支持检测前导码的 1/2/4/8/16 个码元,平衡检测灵敏度与功耗,适配不同通信距离需求。
1.2 工作原理
- 检测逻辑:设备配置 LoRa 频率和 SF 后启动 CAD,仅检测匹配参数的 LoRa 信号(非 RSSI 阈值判断,抗噪声能力更强);
- 中断机制:
- 检测完成:无论是否检测到信号,均触发
SUBGHZ_IT_CAD_DONE中断;
- 检测到信号:额外触发
SUBGHZ_IT_CAD_ACTIVITY_DETECTED中断,通过回调函数区分结果;
- 帧格式依赖:CAD 基于 LoRa 前导码检测,需确保发送端与接收端前导码长度、SF、频率一致。
2. 驱动支持与前提条件
2.1 固件版本要求
- 需使用 STM32Cube_FW_WL_V1.3.0 及以上版本,该版本已内置 CAD 驱动支持;
- 核心驱动文件:
stm32wlxx_hal_subghz.c(HAL 层中断处理);
radio_driver.c/radio.c(SubGHz PHY 层 CAD 逻辑);
- 头文件:
radio.h/radio_ex.h/radio_def.h(CAD 相关宏定义)。
2.2 硬件与工程准备
- 硬件:STM32WL 系列开发板(如 NUCLEO-WL55JC);
- 工程基础:基于 STM32CubeMX 生成的
SubGHz_Phy_Per示例工程(LoRa 调制模式)。
3. 完整配置步骤(基于 SubGHz_Phy_Per 工程)
步骤 1:修改头文件配置(subghz_phy_app.h)
(1)启用 LoRa 调制模式
/* MODEM类型配置:仅启用LoRa */
#define USE_MODEM_LORA 1
#define USE_MODEM_FSK 0
(2)配置 LoRa 核心参数与 CAD 参数
需根据扩频因子(SF)匹配 CAD 检测参数(不同 SF 对应不同阈值,避免误检):
/* LoRa接收核心参数 */
#define RF_FREQUENCY 470000000 /* 信道频率(Hz),需与发送端一致 */
#define LORA_BANDWIDTH 0 /* 带宽:0=125kHz,1=250kHz,2=500kHz */
#define LORA_SPREADING_FACTOR 7 /* 扩频因子(SF7~SF12) */
#define LORA_CODINGRATE 1 /* 编码率:1=4/5,2=4/6,3=4/7,4=4/8 */
#define LORA_PREAMBLE_LENGTH 8 /* 前导码长度(符号数) */
/* 根据SF匹配CAD检测参数(关键!) */
#if LORA_SPREADING_FACTOR == 7 /* SF7示例,其他SF对应参数见文档 */
#define CAD_DETECT_MIN 10
#define CAD_DETECT_PEAK 22
#define CAD_TIMEOUT 0
#define CAD_NB_SYMBOL LORA_CAD_02_SYMBOL /* 检测前导码的2个码元 */
#elif LORA_SPREADING_FACTOR == 8
#define CAD_DETECT_MIN 10
#define CAD_DETECT_PEAK 22
#define CAD_TIMEOUT 0
#define CAD_NB_SYMBOL LORA_CAD_02_SYMBOL
/* 其他SF(SF5~SF12)按文档配置对应参数 */
#endif
步骤 2:声明变量与函数(subghz_phy_app.c)
(1)包含核心头文件
/* USER CODE BEGIN Includes */
#include "radio_driver.h" /* CAD驱动核心头文件 */
#include "stm32_timer.h"
#include "utilities_def.h"
/* USER CODE END Includes */
(2)定义状态标志与计数变量
/* USER CODE BEGIN PV */
static _IO uint32_t RadioCadDone_flag = 0; /* CAD检测完成标志 */
uint32_t cad_max_count = 1000; /* 最大CAD检测次数 */
uint32_t cad_count = 0; /* 当前CAD检测计数 */
uint32_t detect_count = 0; /* 检测到信号的计数 */
/* USER CODE END PV */
(3)声明回调函数与状态机函数
/* USER CODE BEGIN PP */
/* CAD检测完成回调函数 */
static void OnCadDone(bool channelActivityDetected);
/* CAD状态机处理函数(循环触发CAD检测) */
static void Cad_Process(void);
/* USER CODE END PP */
步骤 3:初始化配置(SubghzApp_Init 函数)
(1)注册 CAD 回调函数
/* Radio事件注册:添加CAD完成回调 */
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
RadioEvents.CadDone = OnCadDone; /* 注册CAD回调 */
Radio.Init(&RadioEvents);
(2)配置 SubGHz 参数并启动 CAD
/* USER CODE BEGIN SubghzApp_Init_2 */
Radio.SetChannel(RF_FREQUENCY); /* 配置信道频率 */
/* 配置LoRa接收参数(与发送端一致) */
if ((USE_MODEM_LORA == 1) && (USE_MODEM_FSK == 0))
{
Radio.LoRaSetRxConfig(
LORA_BANDWIDTH,
LORA_SPREADING_FACTOR,
LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT,
LORA_FIX_LENGTH_PAYLOAD_ON,
0,
LORA_IQ_INVERSION_ON,
true,
0,
0,
false
);
APP_TPRINTF("Start CADrn");
Radio.StartCad(); /* 启动首次CAD检测 */
}
/* 注册CAD状态机任务(循环执行) */
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), UTIL_SEQ_RFU, Cad_Process);
/* USER CODE END SubghzApp_Init_2 */
步骤 4:实现回调函数与状态机
(1)CAD 检测完成回调(OnCadDone)
static void OnCadDone(bool channelActivityDetected)
{
if (channelActivityDetected)
{
detect_count++;
APP_TPRINTF("CAD_DETECTED---!rn");
// 检测到信号,启动接收
Radio.Rx(RX_TIMEOUT_VALUE);
}
else
{
APP_TPRINTF("CAD_CLEARrn");
}
APP_TPRINTF("Detect:%d, Total:%drn", detect_count, cad_count);
RadioCadDone_flag = 1; /* 置位标志,触发状态机 */
// 触发状态机任务执行
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
}
(2)CAD 状态机(循环启动检测)
static void Cad_Process(void)
{
if (RadioCadDone_flag == 1 && cad_count < cad_max_count)
{
cad_count++;
// 配置CAD参数(匹配扩频因子)
SUBGRF_SetCadParams(
CAD_NB_SYMBOL,
CAD_DETECT_PEAK,
CAD_DETECT_MIN,
LORA_CAD_RX,
100
);
APP_TPRINTF("Start CAD againrn");
Radio.StartCad(); /* 启动下一次CAD检测 */
RadioCadDone_flag = 0; /* 清除标志 */
}
}
4. 避坑关键要点
- 扩频因子(SF)与 CAD 参数匹配:不同 SF 对应不同的
CAD_DETECT_PEAK、CAD_NB_SYMBOL,如 SF7 用LORA_CAD_02_SYMBOL,SF9 用LORA_CAD_04_SYMBOL,不匹配会导致检测失效;
- 中断处理优先级:CAD 中断需高于低功耗唤醒中断,避免检测结果丢失;
- 低功耗配合:CAD 检测间隙需让设备进入
STDBY_RC模式(文档默认配置),避免空耗;
- 频率一致性:发送端与接收端的 RF 频率必须完全一致,否则无法检测到信号;
- 前导码长度:接收端 CAD 检测的码元数(
CAD_NB_SYMBOL)需小于发送端前导码长度,确保前导码被完整检测。
STM32WL 开启 LoRa CAD 的核心是 “参数匹配 + 中断回调 + 状态机循环”:先按扩频因子配置 CAD 检测参数,再通过回调函数判断是否启动接收,最后用状态机实现循环检测。该方案让设备仅在需要时接收,大幅降低功耗,完美适配电池供电的 LoRa 终端。