4. 射频寄存器与协议栈配置
在 Nordic 无线调试中,真正决定“发得出去、收得回来”的,往往不是应用层代码,而是 RADIO 外设寄存器与协议栈参数的配合。nRF52 与 nRF53 系列都提供独立的 RADIO 硬件外设,它负责 2.4 GHz 物理层收发、地址匹配、CRC、包格式和空中时序;而 SoftDevice(如 S132/S140)或 nRF53 的协议栈则在其上封装了 BLE 链路层、GAP/GATT 与调度器。理解这两层如何分工,是排查“能广播但连不上”“连接后丢包”“距离短”等问题的前提。
RADIO 外设:短距离射频的寄存器骨架
RADIO 外设的核心寄存器可以按“频率—功率—地址—包格式—状态”五组来理解。频率由 FREQUENCY 决定,nRF52 的 BLE 信道映射为 2402 MHz + k×2 MHz,k 取 0~39;广播信道固定为 37/38/39,对应 2402/2426/2480 MHz。发射功率由 TXPOWER 设置,nRF52832 典型档位为 +4、0、−4、−8、−12、−16、−20、−40 dBm,nRF52840 可到 +8 dBm,nRF5340 约 +3 dBm。调试时若发现近距离正常、远距离断连,先确认 TXPOWER 是否被协议栈默认值限制在 0 dBm。
地址与包格式由 BASE0/BASE1、PREFIX0/PREFIX1、PCNF0/PCNF1 共同描述。BLE 广播使用 4 字节访问地址 0x8E89BED6,其中 BASE0 写低 32 位、PREFIX0 写高 8 位;PCNF0 配置 S0/S1 长度、长度字段位数和 CRC 使能,PCNF1 配置最大包长、静态长度、白化使能和字节序。若用私有 2.4 GHz 模式做点对点测试,可自定义地址,但必须保证收发双方 BASE/PREFIX 完全一致,否则会出现“发送完成但接收端无中断”。
状态与事件通过 STATE、EVENTS_READY、EVENTS_ADDRESS、EVENTS_END、EVENTS_DISABLED 观察。典型裸机发送序列是:写 PACKETPTR 指向 RAM 中的包缓冲,置 TASKS_TXEN,等待 EVENTS_READY,再置 TASKS_START,最后等 EVENTS_END 并读 CRCSTATUS。若 CRCSTATUS 为 0,说明对端收到的 CRC 错误,应优先检查白化、字节序和 CRC 初值是否一致。
SoftDevice 与协议栈参数:谁在覆盖寄存器
使用 SoftDevice 时,RADIO 寄存器由协议栈统一管理,应用不能随意直接写 FREQUENCY 或 TXPOWER,否则会与协议栈调度冲突。此时应通过 sd_ble_gap_adv_set_configure()、sd_ble_gap_adv_start()、sd_ble_gap_connect() 等 API 设置广播与连接参数。例如广播间隔由 adv_params.interval 以 0.625 ms 为单位给出,设为 160 即 100 ms;连接间隔在 ble_gap_conn_params_t 中由 min_conn_interval 和 max_conn_interval 以 1.25 ms 为单位给出,设为 24 即 30 ms。若把连接间隔设得过小(如 7.5 ms),而从机延迟和 supervision timeout 不匹配,就会出现频繁断连。
nRF53 的协议栈运行在 network core 上,application core 通过 IPC 与它通信。此时 RADIO 寄存器位于 network core,应用侧只能通过 bt_* API 或 HCI 命令间接配置。调试 nRF53 时,若发现 application core 写寄存器无效,应确认当前是否已启用协议栈、是否在正确的核上操作。对于需要裸机 2.4 GHz 私有协议的场景,可以关闭协议栈,直接使用 nrf_radio_* HAL 或寄存器操作,此时才拥有对 FREQUENCY、TXPOWER、PCNF0/1 的完全控制权。
参数配置示例与观察方法
下面给出一段基于 nRF5 SDK 的广播参数配置示例,用于把广播间隔设为 100 ms、发射功率设为 +4 dBm,并观察实际生效值。示例参数属于教学假设,实际应以芯片手册和协议栈版本为准。
// 广播参数:100 ms 间隔,可连接,使用信道 37/38/39
ble_gap_adv_params_t adv_params = {
.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED,
.p_peer_addr = NULL,
.fp = BLE_GAP_ADV_FP_ANY,
.interval = 160, // 160 × 0.625 ms = 100 ms
.duration = 0, // 0 表示持续广播
.primary_phy = BLE_GAP_PHY_1MBPS,
};
// 发射功率:+4 dBm(需协议栈支持)
sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, adv_handle, 4);
// 启动广播
sd_ble_gap_adv_start(adv_handle, &adv_params, APP_IRQ_PRIORITY_LOWEST);
配置完成后,用 nRF Connect 手机 App 或 Sniffer 观察:广播包应约每 100 ms 出现一次,RSSI 在 1 米处约 −40~−55 dBm。若 RSSI 明显偏低,先查 sd_ble_gap_tx_power_set() 返回值是否为 NRF_SUCCESS,再确认天线匹配和供电。若广播间隔明显偏离 100 ms,检查是否有其他高优先级中断抢占,或协议栈时钟源是否使用外部 32.768 kHz 晶振。
NRF_RADIO,可能触发 HardFault 或导致连接异常。切换模式前应先调用 sd_softdevice_disable() 并确认协议栈已完全停止。常见参数对照与排查要点
| 参数 | 寄存器/API | 典型值 | 异常表现 |
|---|---|---|---|
| 广播信道频率 | FREQUENCY / adv 信道 | 2402/2426/2480 MHz | 收不到广播包 |
| 发射功率 | TXPOWER / sd_ble_gap_tx_power_set | 0~+4 dBm | 距离短、RSSI 低 |
| 访问地址 | BASE0/PREFIX0 | 0x8E89BED6 | 无 ADDRESS 事件 |
| CRC 与白化 | PCNF0/PCNF1 | CRC 使能、白化开 | CRCSTATUS=0 |
| 连接间隔 | ble_gap_conn_params_t | 30~50 ms | 频繁断连或延迟高 |
| ATT MTU | sd_ble_gattc_exchange_mtu_request | 247 字节 | 吞吐上不去 |
最后强调一个工程习惯:每次修改射频参数后,不要只看“有没有连上”,而要同时记录 RSSI、CRCSTATUS、连接间隔实际值和丢包率。把寄存器层与协议栈层的参数分开记录,才能在出现“时好时坏”的偶发问题时快速定位是频率漂移、功率不足,还是协议栈调度被抢占。