概述
标准的蓝牙广播最多 31 字节,在一些情况下 31 字节放不下所需的所有字段,比如既要苹果的 iBeacon 厂商自定义字段还要 UUID、Local Name 等,一个解决思路就是交替发出两个不同的广播,分别满足不同需要。
下文以 TI 的 CC2640 蓝牙芯片为例说明此方法。基于官方例程 ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral,修改 simple_peripheral.c 文件。
设置广播数据
保留原本的 advertData 数组,在广播数据里设置 UUIDs 数据。
static uint8_t advertData[] =
{
// Flags: this field sets the device to use general discoverable
// mode (advertises indefinitely) instead of general
// discoverable mode (advertise for 30 seconds at a time)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16(SIMPLEPROFILE_SERV_UUID),
HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
添加新的广播数据数组,发送不一样的 UUIDs。
static uint8_t advertDataNew[] =
{
0x02, // length of this data
0x01,
0x06,
0x05, // length of this data
0x05,
0xAA,
0x9E,
0xC7,
0x71
};
定义新的事件、周期时钟
#define USER_PERIODIC_EVT 0x0020
#define USER_PERIODIC_EVT_PERIOD 1000
static Clock_Struct USER_periodicClock;
static uint8_t advFlag = 0;
添加周期事件处理函数
在新增自定义处理函数内部进行广播数据切换。
static void USER_performPeriodicTask(void)
{
if (advFlag == 0) {
uint8_t initial_advertising_enable = FALSE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAP_UpdateAdvertisingData(selfEntity, TRUE,
sizeof(advertData), advertData );
initial_advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
advFlag = 1;
}
else {
uint8_t initial_advertising_enable = FALSE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAP_UpdateAdvertisingData(selfEntity, TRUE,
sizeof(advertDataNew), advertDataNew);
initial_advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
advFlag = 0;
}
}
初始化并启动周期时钟![点击并拖拽以移动]()
在 SimpleBLEPeripheral_init 函数中初始化时钟,用于周期触发事件,然后改变广播数据。
Util_constructClock(&USER_periodicClock, SimpleBLEPeripheral_clockHandler,
USER_PERIODIC_EVT_PERIOD, 0, false, USER_PERIODIC_EVT);
Util_startClock(&USER_periodicClock);
增加监听新增的自定义事件
在 SimpleBLEPeripheral_taskFxn 函数中进行时钟事件处理
//修改事件监听调用,添加自定义事件 USER_PERIODIC_EVT
events = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS | USER_PERIODIC_EVT, ICALL_TIMEOUT_FOREVER);
筛选自定义事件并处理
if (events)
{
...
//添加对应的时间处理,调用函数进行广播数据切换
if (events & USER_PERIODIC_EVT)
{
events &= ~USER_PERIODIC_EVT;
Util_startClock(&USER_periodicClock);
USER_performPeriodicTask();
}
}
参考