蓝牙----蓝牙连接建立_主从GAP初始化
主机GAP初始化–扫描
主机扫描设置:
1.注册回调函数
1.1注册GAP_Role层的回调函数SimpleCentral_scanCb
1.2设置扫描事件掩码,使能的事件在SimpleCentral_scanCb中有处理函数
2.设置扫描物理层参数
3.设置扫描配置:
3.1保存扫描包的地址和地址类型
3.2设置扫描 1M速率
3.3使能数据链路层过滤器,过滤重复
4.设置扫描的广播包PDU类型
5.启动广播
case GAP_DEVICE_INIT_DONE_EVENT:
{
uint8_t temp8;
uint16_t temp16;
gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
// Setup scanning
// For more information, see the GAP section in the User's Guide:
// http://software-dl.ti.com/lprf/ble5stack-latest/
// Register callback to process Scanner events
// 注册扫描回调函数
GapScan_registerCb(SimpleCentral_scanCb, NULL);
// Set Scanner Event Mask
//设置掩码,使能GAP事件,当发生使能的事件后,会调用响应回调函数SimpleCentral_scanCb
//扫描启动、扫描停止和收到广播。
GapScan_setEventMask(GAP_EVT_SCAN_ENABLED | GAP_EVT_SCAN_DISABLED |
GAP_EVT_ADV_REPORT);
// Set Scan PHY parameters
//设置扫描物理层参数
GapScan_setPhyParams(DEFAULT_SCAN_PHY, SCAN_TYPE_PASSIVE,
SCAN_PARAM_DFLT_INTERVAL, SCAN_PARAM_DFLT_INTERVAL);
// Set Advertising report fields to keep
// 设置只关注广播的地址和地址类型
// 需要存储在AdvRptList中的GapScan_Evt_AdvRpt_t中字段的位掩码
temp16 = SC_ADV_RPT_FIELDS;
GapScan_setParam(SCAN_PARAM_RPT_FIELDS, &temp16);
// Set Scanning Primary PHY
// 设置扫描 1M速率
temp8 = DEFAULT_SCAN_PHY;
GapScan_setParam(SCAN_PARAM_PRIM_PHYS, &temp8);
// Set LL Duplicate Filter
// 设置数据链路层 过滤重复
temp8 = SCAN_FLT_DUP_ENABLE;
GapScan_setParam(SCAN_PARAM_FLT_DUP, &temp8);
// Set PDU type filter -
// Only 'Connectable' and 'Complete' packets are desired.
// It doesn't matter if received packets are
// whether Scannable or Non-Scannable, whether Directed or Undirected,
// whether Scan_Rsp's or Advertisements, and whether Legacy or Extended.
//设置扫描的广播包PDU类型
//完整的可连接的PDU
temp16 = SCAN_FLT_PDU_CONNECTABLE_ONLY | SCAN_FLT_PDU_COMPLETE_ONLY;
GapScan_setParam(SCAN_PARAM_FLT_PDU_TYPE, &temp16);
scMaxPduSize = pPkt->dataPktLen;
// Enable "Discover Devices", "Set Scanning PHY", and "Set Address Type"
// in the main menu
tbm_setItemStatus(&scMenuMain,
SC_ITEM_STARTDISC | SC_ITEM_SCANPHY, SC_ITEM_NONE);
Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Initialized");
Display_printf(dispHandle, SC_ROW_NUM_CONN, 0, "Num Conns: %d", numConn);
// Display device address
Display_printf(dispHandle, SC_ROW_IDA, 0, "%s Addr: %s",
(addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
Util_convertBdAddr2Str(pPkt->devAddr));
#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)
if (addrMode > ADDRMODE_RANDOM)
{
// Update the current RPA.
// 更新RPA地址
memcpy(rpa, GAP_GetDevAddress(FALSE), B_ADDR_LEN);
Display_printf(dispHandle, SC_ROW_RPA, 0, "RP Addr: %s",
Util_convertBdAddr2Str(rpa));
// Create one-shot clock for RPA check event.
Util_constructClock(&clkRpaRead, SimpleCentral_clockHandler,
SC_READ_RPA_PERIOD, 0, true, SC_EVT_READ_RPA);
}
#endif // PRIVACY_1_2_CFG
break;
}
从机GAP初始化–广播
广播包括传统广播、扩展广播、周期广播
- 扩展广播,既在主广播信道(37/38/39)上发送信息,也在其它信道(辅广播信道)上发送,
主广播信道只能使用 1M、Coded 等两种 PHY,而辅广播信道 1M、 2M、Coded 皆可 - 周期广播通过一个不可连接、不可扫描的扩展广播实现。
广播类型
- 可连接:接受连接建立请求
- 可扫描:接受扫描请求,并回复扫描响应
- 定向:只用于可连接广播,接受特定方的连接建立请求
- 高占空比:更高的频率重复发送广播数据,用于实现快速重连(定向可连接广播),最长1.28s
CC2640R2F主机GAP实现
1.设置广播参数:可扫描的、可连接的
2.初始化广播:
2.1注册广播回调函数,广播参数,广播句柄
2.2修改 广播 的内容,明确是广播类型数据
2.3修改 扫描应答 的内容,明确是扫描应答(带GAP_ADV_PROP_SCANNABLE的广播参数)
2.4设置广播事件掩码,与广播回调函数相对应
3.启动广播
case GAP_DEVICE_INIT_DONE_EVENT:
{
bStatus_t status = FAILURE;
gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
if(pPkt->hdr.status == SUCCESS)
{
// Store the system ID
uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
// use 6 bytes of device address for 8 bytes of system ID value
// pMsg包含设备地址
systemId[0] = pPkt->devAddr[0];
systemId[1] = pPkt->devAddr[1];
systemId[2] = pPkt->devAddr[2];
// set middle bytes to zero
systemId[4] = 0x00;
systemId[3] = 0x00;
// shift three bytes up
systemId[7] = pPkt->devAddr[5];
systemId[6] = pPkt->devAddr[4];
systemId[5] = pPkt->devAddr[3];
// Set Device Info Service Parameter
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Initialized");
//启动了两个广播
//advParamLegacy不同:
//1.其中一个PHY使用的是1M,另一个为了更长的距离PHY使用1Mcode编码
//2.广播包类型(eventProps)不同:
//具有 GAP_ADV_PROP_CONNECTABLE 和 GAP_ADV_PROP_SCANNABLE广播包,可连接,并接受对方发来的扫描请求回复扫描响应
//仅包含 GAP_ADV_PROP_CONNECTABLE 的广播包,表达设备可连接
// Setup and start Advertising
// For more information, see the GAP section in the User's Guide:
// http://software-dl.ti.com/lprf/ble5stack-latest/
//设置并初始化广播
// Temporary memory for advertising parameters for set #1. These will be copied
// by the GapAdv module
//设置广播报文类型参数:可扫描的、可连接的
GapAdv_params_t advParamLegacy = GAPADV_PARAMS_LEGACY_SCANN_CONN;
// Create Advertisement set #1 and assign handle
// 设置广播 1.初始化广播 每次广播的回调,广播的参数,广播句柄
status = GapAdv_create(&SimplePeripheral_advCallback, &advParamLegacy,
&advHandleLegacy);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Load advertising data for set #1 that is statically allocated by the app
//设置广播 2.修改广播的内容,明确是广播
status = GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_ADV,
sizeof(advertData), advertData);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Load scan response data for set #1 that is statically allocated by the app
//设置广播 3.修改 扫描应答 的内容,明确是扫描应答
status = GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_SCAN_RSP,
sizeof(scanRspData), scanRspData);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Set event mask for set #1
//设置广播 4.设置GAP层的广播事件,与SimplePeripheral_advCallback对应
status = GapAdv_setEventMask(advHandleLegacy,
GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
GAP_ADV_EVT_MASK_SET_TERMINATED);
// Enable legacy advertising for set #1
//开始广播
status = GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Use long range params to create long range set #2
GapAdv_params_t advParamLongRange = GAPADV_PARAMS_AE_LONG_RANGE_CONN;
// Create Advertisement set #2 and assign handle
// 1.创建广播,设置广播回调函数,广播的参数,广播句柄
status = GapAdv_create(&SimplePeripheral_advCallback, &advParamLongRange,
&advHandleLongRange);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Load advertising data for set #2 that is statically allocated by the app
//2.设置广播包数据,明确是广播数据
status = GapAdv_loadByHandle(advHandleLongRange, GAP_ADV_DATA_TYPE_ADV,
sizeof(advertData), advertData);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
// Set event mask for set #2
//3.设置GAP层的广播事件,与SimplePeripheral_advCallback对应
status = GapAdv_setEventMask(advHandleLongRange,
GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
GAP_ADV_EVT_MASK_SET_TERMINATED);
// Enable long range advertising for set #2
//4.启动广播
status = GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
#ifdef PTM_MODE
// Enable "Enable PTM Mode" option
tbm_setItemStatus(&spMenuMain, SP_ITEM_PTM_ENBL, SP_ITEM_NONE);
#endif
// Display device address
Display_printf(dispHandle, SP_ROW_IDA, 0, "%s Addr: %s",
(addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
Util_convertBdAddr2Str(pPkt->devAddr));
#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)
if (addrMode > ADDRMODE_RANDOM)
{
SimplePeripheral_updateRPA();
// Create one-shot clock for RPA check event.
Util_constructClock(&clkRpaRead, SimplePeripheral_clockHandler,
SP_READ_RPA_EVT_PERIOD, 0, true,
(UArg) &argRpaRead);
}
#endif // PRIVACY_1_2_CFG
}
广播参数分析
eventProps :广播类型:可被扫描,可被连接,传统广播
primIntMin :广播间隔最小值
primIntMax :广播间隔最大值
primChanMap 广播信道:ALL_37 38 39
peerAddrType,peerAddr 设置定向广播的对端地址(eventProps 设置GAP_ADV_PROP_DIRECTED)
filterPolicy 扫描和连接请求过滤策略
txPower :发送功率
primPhy :主广播物理层
secPhy :辅广播物理层
#define GAPADV_PARAMS_LEGACY_SCANN_CONN { \
.eventProps = GAP_ADV_PROP_CONNECTABLE | GAP_ADV_PROP_SCANNABLE | \
GAP_ADV_PROP_LEGACY, \
.primIntMin = 160, \
.primIntMax = 160, \
.primChanMap = GAP_ADV_CHAN_ALL, \
.peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID, \
.peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, \
.filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ, \
.txPower = GAP_ADV_TX_POWER_NO_PREFERENCE, \
.primPhy = GAP_ADV_PRIM_PHY_1_MBPS, \
.secPhy = GAP_ADV_SEC_PHY_1_MBPS, \
.sid = 0 \
}