BLE广播包怎么设置?新手必看的31字节数据填法攻略

发布时间:2026-03-27 · 阅读时长:13分钟

先说结论

蓝牙BLE广播包就31字节,塞什么、怎么塞,直接决定你的设备能不能被搜到、搜到后用户愿不愿意连。核心原则:名称要让人认出来、UUID要匹配手机App的预期、厂商数据要实用别浪费字节。 参数调错了最常见的结果就两种——要么手机根本搜不到,要么搜到了连不上。看完这篇,你自己能配出完整的广播包。


你的设备为什么搜不到?先搞懂广播包是什么

蓝牙BLE设备工作时分两个阶段:广播阶段(我在这里,谁来连我)和连接阶段(咱俩建立私密通道)。广播阶段设备不停往外发"自我介绍"包,手机蓝牙就在这个阶段扫到你。

广播包格式:长度(1字节) + 类型(1字节) + 数据(N字节)

每段数据前面的"长度"字段,指的是从类型字节到最后一个数据字节的总字节数,不是数据本身的字节数。新手最容易在这里搞混,写成实际数据长度,结果手机解析出错。

一个能用的最小广播包:

02 01 06  → 长度2,类型0x01(flags),值0x06
08 09 54 58 38 38 30 30 31 → 长度8,类型0x09(完整名称),数据"TX88001"
03 03 18 0D → 长度3,类型0x03(16bit UUID列表),数据0x180D(心率服务,可替换)

广播包里该填什么?

1. Flags(必须有,不填系统会报错)

Flags告诉手机你的设备是什么类型BLE设备,这个字段系统层要用,不填的话Android和iOS行为不一致。

// Flags字段(必填)
// bit1=1:LE General Discoverable Mode(可被发现)
// bit2=0:BR/EDR Not Supported(不支持经典蓝牙,纯BLE)
// 0x06 = 二进制 00000110,对应上面两个bit
uint8_t adv_flags[] = { 0x02, 0x01, 0x06 };

2. 设备名称(用户第一眼看到的就是它)

名称是用户判断"搜到的是不是我的设备"的唯一依据。蓝牙SIG标准里,类型0x09是完整名称,0x08是缩短名称(用于空间不够时替代)。

// 完整名称(TX88001,出厂默认,可定制)
uint8_t device_name[] = {
    0x08,       // 长度8字节
    0x09,       // 类型:Complete Local Name
    'T', 'X', '8', '8', '0', '0', '1'
};

// 如果空间不够用缩短名称(只显示"TX8800",手机App仍能识别)
uint8_t short_name[] = {
    0x06,       // 长度6字节
    0x08,       // 类型:Shortened Local Name
    'T', 'X', '8', '8', '0', '0'
};

实战经验:

3. 服务UUID(决定App能不能认出你是哪种设备)

UUID是设备的"身份类型",手机App扫描时就是靠这个过滤设备的。比如心率带广播里带了0x180D心率服务UUID,手机上装的心率App扫到就认出来。

常用标准16bit UUID:

UUID服务类型常见应用
0x180D心率服务心率带、心率手环
0x180F电池服务所有电池供电设备
0x1816体温服务额温枪、体温贴
0x181A环境感知服务温湿度传感器
0x181C人体存在检测PIR、人体感应
0x1810血压服务血压计
0x180A设备信息所有设备可选

4. 外观类型(决定手机显示什么图标)

外观类型告诉手机你的设备外观分类,系统会根据这个显示对应图标。

外观值设备类型
0x0080Generic Tag(通用标签/防丢器)
0x00C0Generic Wearable(可穿戴设备)
0x0440Heart Rate Sensor(心率传感器)
0x03D0Thermometer(温度计)
0x0300Generic Phone(手机)

5. 厂商自定义数据(最有价值的部分)

类型0xFF是厂商自定义数据段,你可以往里填任何业务相关的信息——电池电量、固件版本、设备状态。手机App扫描时不需要建立连接就能读到,这是BLE广播最有价值的能力之一。

// 厂商自定义数据示例
// 字节结构:[长度][0xFF][厂商ID高字节][厂商ID低字节][业务数据1][业务数据2]
uint8_t mfg_data[] = {
    0x05,       // 总长度5字节(类型1字节 + 数据4字节)
    0xFF,       // 厂商自定义数据标识
    0x59, 0x54, // 厂商ID:0x5954(可自定义,测试用0xFFFF)
    0x64,       // 电池电量:100%
    0x01        // 设备状态:1=正常,0=异常
};

实际应用场景举例:

广播参数:间隔、功率、频道怎么配?

数据格式对了只是第一步,物理参数不对照样搜不到或功耗爆炸。

参数可调范围实战建议
发射功率-40dBm ~ +10dBm室内设备一般-8~0dBm够用,调高不省钱反而费电
广播间隔20ms ~ 10s防丢器/Beacon用100-200ms,普通设备500ms-1s
广播频道Ch37/Ch38/Ch39三个全开,别省

实测功耗参考(nRF52832):

广播间隔平均广播电流CR2032续航估算
100ms~15μA6-12个月
500ms~3μA1.5-2年
1s~1.5μA2-3年
2s~0.8μA3年+

扫描响应包:多给你31字节

广播包只有31字节,不够用怎么办?手机主动扫描时会发一个scan request,设备可以回复scan response,这是额外的31字节。

// 扫描响应包里放什么?
// 1. 完整设备名称(广播包里用的是缩短名)
// 2. 设备序列号
// 3. OTA升级标识
// 4. 连接密码/Token

static uint8_t scan_rsp_data[] = {
    0x0B,       // 长度11
    0x09,       // 类型:Complete Local Name
    'T', 'X', '8', '8', '0', '0', '1', '-', 'A', 'B',  // 完整名称
};

完整配置代码(Nordic nRF52832)

#include "ble.h"
#include "nrf_sdh_ble.h"

#define APP_BLE_OBSERVER_PRIO 3
#define APP_BLE_CONN_CFG_TAG  1

// 完整广播数据
static uint8_t m_adv_data[] = {
    0x02, 0x01, 0x06,                      // Flags: BLE通用发现
    0x08, 0x09, 'T', 'X', '8', '8', '0',  // 设备名TX88001(前半段)
    0x00, 0x03, 0x03, 0x0D, 0x18,         // 心率服务UUID 0x180D
    0x05, 0xFF, 0x59, 0x54, 0x64, 0x01    // 厂商ID 0x5954 + 电量100% + 状态1
};

// 扫描响应数据
static uint8_t m_scan_rsp_data[] = {
    0x0C, 0x09, 'T', 'X', '8', '8', '0',  // 完整设备名
    0x30, 0x30, 0x31, 0x2D, 0x50, 0x52,   // TX88001-PR(带型号后缀)
};

// 广播参数
static ble_gap_adv_params_t m_adv_params = {
    .type = BLE_GAP_ADV_TYPE_ADV_IND,     // 可连接广播
    .p_peer_addr = NULL,                   // 广播给所有人
    .fp = BLE_GAP_ADV_FP_ANY,             // 允许任何人扫描
    .interval = 320,                       // 间隔=320×0.625ms=200ms
    .timeout = 0,                          // 0=持续广播
};

// 启动广播
void advertising_init(void) {
    ble_gap_adv_data_t adv_data = {
        .adv_data.p_data = m_adv_data,
        .adv_data.size = sizeof(m_adv_data),
        .scan_rsp_data.p_data = m_scan_rsp_data,
        .scan_rsp_data.size = sizeof(m_scan_rsp_data),
    };
    
    sd_ble_gap_adv_set_configure(&m_adv_params, &adv_data);
    sd_ble_gap_adv_start(&m_adv_params, APP_BLE_CONN_CFG_TAG);
}

常见问题Q&A

Q1:广播包31字节怎么分配最合理?

我的经验分配方式:Flags 3字节 + 名称 8-12字节 + 服务UUID 3-6字节 + 厂商数据 5-6字节 = 19-27字节,留4-6字节给扩展。这样扫描响应包里就不用再塞名称了,全放完整信息和自定义数据。

Q2:广播间隔设了100ms,功耗好像比预期高很多?

确认一下发射功率。100ms间隔 + 0dBm功率平均电流约15μA,但如果功率设成+4dBm,平均电流会到25-30μA,续航直接打7折。先量一下实际发射电流,再确认参数。

Q3:手机搜到了但是连不上,是什么问题?

广播包本身没问题的情况下,连不上一般两个原因:①设备在广播包里声明的是不可连接广播类型(ADV_NONCONN_IND);②设备已经在和其他主机连接了,BLE从机同一时间只能连一个主机。检查广播类型参数。

Q4:厂商ID怎么选?

蓝牙SIG分配的正式ID可以免费申请(bluetooth.com/assigned-numbers/company-identifiers)。内部测试用0xFFFF,正式产品建议申请正式ID或者用固定自定义值(比如0x5954)。选ID的时候注意别和知名大厂冲突。

Q5:多设备同时广播会互相干扰吗?

BLE三个频道都是随机跳频,设备多了信道冲突是概率问题,10个以内设备基本感知不到。如果做50+设备mesh场景,用随机延迟广播能显著改善。颖特新部分模块内置广播随机跳频策略,批量部署时更稳定。

选型速查表

产品类型推荐广播配置典型模块型号参考价格
防丢器100ms间隔,厂商数据带电量TX88001/TX890018-15元
温湿度传感器1s间隔,短名称+UUIDTX8803218-25元
门锁500ms间隔,厂商数据带状态TX8804025-35元
Beacon信标100ms间隔,厂商数据带IDTX8801012-20元

技术问题?查看更多 开发教程文章