ESP32 C3开发实战 -8(BLE广播数据)

📅 2026/7/9 1:19:17 👁️ 阅读次数 📝 编程学习
ESP32 C3开发实战 -8(BLE广播数据)

一、基础规则:广播包整体结构

BLE 广播包(Advertising Packet)分两大块:

  1. 广播头部(Packet Header):蓝牙底层链路层控制信息(芯片自动填充,应用层不用管)
  2. AD 数据载荷(Advertising Data / Scan Response Data):开发者可自定义的业务数据,最多 31 字节
    • ADV_DATA:主机扫描时直接收到的广播数据(最多 31 字节)
    • SCAN_RSP:主机发 Scan Request 后设备回复的附加数据(额外 31 字节)

所有用户可见的名称、服务 UUID、厂商数据,全部放在「AD 载荷」里,由多条AD 结构(AD Structure)顺序拼接而成。

二、单条 AD 结构通用固定格式(核心)

每一段信息(名称、Flags、厂商数据等)都遵循统一 3 段式结构:

plaintext

[1字节 Length] + [1字节 AD Type] + [N字节 AD Data Payload]
  1. Length(长度字节):等于后面「AD Type + AD Payload」的总字节数
    • 例:Type1 字节 + 负载 2 字节 → Length = 0x03
  2. AD Type(数据类型):标准编号,规定这段数据是什么含义(蓝牙 SIG 规范定义)
  3. AD Payload(有效载荷):该类型对应的实际内容,长度 = Length - 1

多条 AD 结构紧密拼接,中间无分隔符,扫描工具靠Length逐个拆分解析

三、BLE 最常用标准 AD Type(对照你截图里的字段)

1. 0x01 Flags 标志位(必带,几乎所有设备广播第一段)

  • 长度固定:Length=0x02,Payload 2bit 标志位
  • 关键 bit 定义:
    • Bit0:LE Limited Discoverable 有限可发现(短时广播)
    • Bit1:LE General Discoverable 通用可发现(长期广播)
    • Bit2:BR/EDR Not Supported = 1 → 纯 BLE 设备,无经典蓝牙
    • Bit3:LE+BR/EDR 共存设备
  • 示例值0x05= 0b00000101:有限可发现、无经典蓝牙

2. 服务 UUID 类(宣告设备支持的 BLE GATT 服务)

3. 设备名称类

  • 0x08 Shortened Local Name:缩短本地名(名称超长时截断)
  • 0x09 Complete Local Name:完整本地名称 Payload 直接存 ASCII 字符串

4. Appearance 设备外观 0x19

2 字节数值,蓝牙 SIG 预定义设备图标分类:手环、温度计、体重秤、通用设备等0x0000= 无分类通用 BLE 设备,手机不显示专属图标

5. LE 蓝牙地址 0x1B

广播携带自身 BLE MAC 地址,6 字节,用于区分设备

6. 厂商自定义数据 0xFF Manufacturer Specific Data

最常用私有业务段,也是你文档重点: Payload 格式固定:[2字节 Company ID] + [厂商自定义私有数据]

  • 前 2 字节:蓝牙联盟分配的厂商 ID
  • 剩余字节:厂商自由定义状态、参数、MAC、故障码等,无规范限制

四、可选扩展 AD Type(日常开发高频)

  1. 0x0A Tx Power Level:发射功率,用于 RSSI 测距定位
  2. 0x14 Service Data:服务配套数据(BLE 透传、传感器实时值广播)
  3. 0x16 16-bit Service Data:绑定 16bit 服务的实时数据(门锁、传感器常用)
  4. 0x29 Mesh Data:蓝牙 Mesh 组网广播
  5. 0x2A Mesh Beacon:Mesh 信标

五、广播数据包两种载体区分

  1. ADV_DATA(主广播数据,最大 31 字节)设备主动向外广播,手机不用额外请求就能直接收到; 业务核心数据(名称、厂商状态、基础服务)尽量放这里。
  2. SCAN_RSP(扫描响应,额外 31 字节)手机发送 Scan Request 包后,设备才会回复; 适合放次要数据:超长设备名、额外服务、扩展厂商信息。

总可用数据上限:ADV 31B + SCAN_RSP 31B = 62 字节

六、贴上实例代码

// 启动BLE广播

void BleAdvertise(void)

{

LOG(BLE_TAG, "BleAdvertise()");

if(BleState!=BLE_STOP) return;

if (!ble_hs_synced())

{

ESP_LOGW(BLE_TAG, "BLE is not synced,return");

return;

}

struct ble_hs_adv_fields Fields = {0};

Fields.name = (uint8_t *)DeviceName;

Fields.name_len = strlen(DeviceName);

Fields.name_is_complete = 1;

Fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;

Fields.uuids16 = (ble_uuid16_t[]){BLE_UUID16_INIT(0x180A)}; //设备信息服务UUID

Fields.num_uuids16 = 1;

Fields.uuids16_is_complete = 1;

if (ble_gap_adv_set_fields(&Fields) != 0)

{

ESP_LOGE(BLE_TAG, "Set Ble Advertise field fail");

return;

}

struct ble_gap_adv_params AdvPara = {0};

AdvPara.conn_mode = BLE_GAP_CONN_MODE_UND;

AdvPara.disc_mode = BLE_GAP_DISC_MODE_GEN; if (ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &AdvPara, BleGapEventHdl, NULL) != 0)

{

ESP_LOGE(BLE_TAG, "Ble advertise start fail");

return;

}

BleState=BLE_ADVERTISING;

LOG(BLE_TAG, "BLE advertising (Device: %s)", LB_Mode);

}