【从零开始】手写BLE协议栈(1-3)实验: 01_tx_advertise
1-3 动手实验:编译运行 01_tx_advertise
本篇是第 1 章的配套实验,将 1-1 和 1-2 中讲解的 RADIO 操作与 ADV_NONCONN_IND 广播完整跑通。
一、概述
01_tx_advertise 是整个系列中最简单的 Demo:它驱动 nRF52832 的 RADIO 外设,在 37/38/39 三个广播信道上循环发送 ADV_NONCONN_IND 包。这个例程没有任何 RX 逻辑,是一个纯粹的"只发不收"广播器。
通过本实验,你将验证:
- HFXO 时钟启动与 RADIO 配置是否生效
- PDU 构建(Header + AdvA + AdvData)是否正确
- 手机或 Bumble 扫描器能否看到名为 "ZephyrRaw" 的设备
二、实验环境
| 项目 | 说明 |
|---|---|
| 开发板 | nRF52 DK (PCA10040) — nRF52832 |
| 测试工具 | nRF52840 Dongle + bumble_scan_req.py(或 nRF Connect App) |
| 构建系统 | Zephyr west + GCC (zephyr-sdk-0.17.4) |
| 串口查看 | 任何串口终端(115200 baud,连接 DK 板载 J-Link CDC) |
三、编译与烧录
前提:已按 0-2 环境搭建 完成 Zephyr 环境配置,并在
zephyr/目录下激活了虚拟环境(..\.venv\Scripts\Activate.ps1)。
3.1 编译
west build -b nrf52dk/nrf52832 .\write-BLE-stack-from-scratch\01_tx_advertise\ -p
编译输出(关注 Memory region):
Memory region Used Size Region Size %age Used
FLASH: 45668 B 512 KB 8.71%
RAM: 13360 B 64 KB 20.39%
3.2 烧录
west flash
四、串口日志
烧录完成后,串口终端会输出以下内容:
*** Booting Zephyr OS build v4.3.0-4808-ga5d4626b8c16 ***
=== BLE PHY Raw TX Demo (HAL API) ===
Device Name: ZephyrRaw
Address: C6:A5:E4:D3:C2:E1 (Random Static)
HFCLK (16MHz HFXO) started
Radio configured via HAL: BLE 1M, AA=0x8E89BED6, CRC_IV=0x555555
PDU built: type=0x02 tx_addr=1 len=20
Starting advertising on channels 37/38/39...
Sent 10 advertising events
Sent 20 advertising events
Sent 30 advertising events
...
日志中的关键字段解读:
type=0x02:PDU Type = ADV_NONCONN_IND(不可连接的非定向广播)tx_addr=1:TxAdd=1 表示使用随机地址AA=0x8E89BED6:BLE 规范规定的广播接入地址,所有广播包都用这个值CRC_IV=0x555555:广播信道的 CRC 初始值,同样由规范固定
五、运行测试
方法 A:nRF Connect App
打开手机上的 nRF Connect App → Scan,你会看到名为 "ZephyrRaw" 的设备。

方法 B:bumble_scan_req.py
使用 nRF52840 Dongle 运行 Bumble 扫描器:
.\write-BLE-stack-from-scratch\tools\venv\Scripts\python.exe `
.\write-BLE-stack-from-scratch\tools\bumble_scan_req.py `
--transport usb:2FE3:000B `
--target C6:A5:E4:D3:C2:E1 `
--duration 5
输出示例:
Bumble BLE Active Scanner
Transport : usb:2FE3:000B
Target : C6:A5:E4:D3:C2:E1
Duration : 5s
Starting Active Scan for 5s ...
────────────────────────────────────────────────────────────
ADV #1: ADV_NONCONN from C6:A5:E4:D3:C2:E1
────────────────────────────────────────────────────────────
RSSI: -68 dBm
Address Type: Random
AD Structures (2):
[Flags] (1 bytes): 06 => LE General Discoverable | BR/EDR Not Supported
[Complete Local Name] (9 bytes): "ZephyrRaw"
============================================================
Scan completed.
ADV received : 14
SCAN_RSP received: 0 ← ADV_NONCONN 不会回复 SCAN_RSP
Unique devices : 1
============================================================
注意 SCAN_RSP received: 0 — 因为 ADV_NONCONN_IND 类型的广播不会响应扫描请求(Scanner 发了 SCAN_REQ 也会被忽略),这正是它与 ADV_IND 的关键区别。
方法 C: 使用 BPA-low-energy 抓包



六、关键概念图
广播事件时序
┌──────────┐ ┌──────────┐ ┌──────────┐
│ CH 37 │ │ CH 38 │ │ CH 39 │ k_msleep(100)
│ ADV_IND │ │ ADV_IND │ │ ADV_IND │ ───────────►
│ TX only │ │ TX only │ │ TX only │
└──────────┘ └──────────┘ └──────────┘
│ │ │
▼ ▼ ▼
2402 MHz 2426 MHz 2480 MHz
PDU 内存布局
字节偏移 值 说明
[0] 0x42 Header: PDU Type=0x02 (ADV_NONCONN_IND), TxAdd=1
[1] 0x14 Length: 20 字节
[2..7] E1:C2:.. AdvA (6 字节, 小端序) → 显示为 C6:A5:E4:D3:C2:E1
[8..9] 02 01 AD #1: Len=2, Type=0x01 (Flags)
[10] 06 Flags value: LE General Discoverable + BR/EDR Not Supported
[11..12] 0A 09 AD #2: Len=10, Type=0x09 (Complete Local Name)
[13..21] "ZephyrRaw" 设备名(9 字节 ASCII)
本系列教程同款硬件:👇
芯片: nRF 52832 开发板
工具: nRF 52840 BLE Dongle 蓝牙嗅探器
工具: 逻辑分析仪
工具: BPA low energy 蓝牙分析仪
本文版权归作者:ixbwer所有,转载请注明原文链接:https://www.cnblogs.com/ixbwer/p/19796872,否则保留追究法律责任的权利。

浙公网安备 33010602011771号