【从零开始】手写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" 的设备。

image

方法 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 抓包

image

image

image

六、关键概念图

广播事件时序

  ┌──────────┐    ┌──────────┐    ┌──────────┐
  │  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 蓝牙分析仪

posted @ 2026-03-30 17:27  ixbwer  阅读(4)  评论(0)    收藏  举报