nRF52-Note(06)-广播Advertising
一、开发环境及工具
-
nRF5 SDK v15.3.0
-
IAR For ARM V7.80.4 / Keil uVision5(MDK-ARM) V5.33
-
Bluetooth Core Specification V4.2 / V5.x
-
此工程源码下载路径 : https://gitee.com/amx/nrf52xx-project
-
参考好文链接(部分内容从其中摘取):
https://www.cnblogs.com/someone-device/p/12213388.html
https://blog.csdn.net/zhoutaopower/article/details/95104632
http://www.wowotech.net/sort/bluetooth
https://blog.csdn.net/Hh20161314/article/details/104501877
https://blog.csdn.net/qq_36347513/article/details/104264490
二、nRF52系列Bluetooth 5.x特性
三、广播信道
- 在蓝牙核心规范V4.2中,广播信道使用37/38/39三个通道,其余37个是数据通道:

四、数据结构
- BLE数据包结构:preamble(前导码/报头)、access address(接入地址)、PDU(数据包)、CRC(校验码)

-
PDU分为两类,广播类型PDU和数据类型PDU
-
广播(Advertising)是一种单向的发送机制。想要被搜索到的设备可以以20毫秒到 10秒钟的时间间隔发送一段数据包。使用的时间间隔越短,电池消耗的越快,但设 备被发现的速度也就会快。数据包长度最多47个字节,由以下部分组成:
- 1 byte preamble(1字节做报头) - 4 byte access address(4字节做地址) - 39 bytes advertising channel PDU(39个字节用于PDU数据包) - 3 bytes CRC(3个字节用于CRC数据校验) -
下图是广播通道PDU分解:

- 对于广告通信信道,地址部分永远都是0x8E89BED6
- 对于其它数据信道,地址部分由不同的连接决定
- PDU数据也拥有自己的数据报头: (2个字节:声明有效载荷数据的长度和类型——设备是否支持连接等等)和有效载荷数据(最多37个字节)
- 有效载荷数据中的头6个字节是设备的MAC地址,所以实际信息数据最高可占31个字节

- 在Header中PDU Type分下面7种(四个广播类型的PDU、两个扫描类型的PDU、一个发起连接PDU):

-
在Header中Length: PDU的长度,6 bits,有效范围 6-37 octets
-
Header成员间的关系:


- Payload部分分解(ADV_IND类型):

可以看到,AdvData由一个个AD Structure组成,每个AD Structure包含3个部分:
- AD length:AD Type 和AD Data的长度
- AD Type:AD Data的数据含义
- AD Data:AD Type所指示的数据
结合函数ble_advdata_encode(),对理解AD Structure会有更深的印象:
ret_code_t ble_advdata_encode(ble_advdata_t const * const p_advdata,uint8_t * const p_encoded_data,uint16_t * const p_len);
在ble_gap.h中定义的AD Type类型:
/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format* @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm* @{ */
#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */
#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */
#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */
#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */
#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */
#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */
#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */
#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */
#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */
#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */
#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */
#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */
#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */
#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */
#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */
#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */
#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */
#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */
#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */
#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */
#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */
/**@} */
五、扫描响应包
广播包有两种:广播数据包(Advertising Data)和扫描相应包(Scan Response),其中广播数据包是每个设备必须广播的,而扫描响应包是可选的。
每个包都是 31 个字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分:
- 有效数据部分:包含若干个广播数据单元,称为 AD Structure。AD Structure 的组成是:第一个字节是长度值 Len,表示接下来的 Len 个字节是数据部分。数据部分的第一个字节表示数据的类型 AD Type,剩下的 Len - 1 个字节是真正的数据 AD Data。其中 AD Type 非常关键,决定了 AD Data 的数据代表的是什么和怎么解析。
- 无效数据部分:因为广播包的长度必须是 31 个字节,如果有效数据部分不到 31 个字节,剩下的就用 0 补全。这部分的数据是无效的,解析时忽略即可。
而扫描响应包是为了给广播一个额外的 31 字节数据,用于主机 主动扫描 情况下,反馈数据使用。
不管广播数据包还是扫描响应包,都只提供 31 个字节的空间,因此需要注意可使用的空间。如果在配置广播数据时,长度大于31字节,会导致运行报错或者广播名称自动变短(nrf52xxx SDK 15.3版本)。
比如私有任务的 128bit UUID(占用较多字节),我们需要反馈给主机的时候,我们可以采用扫描响应包的方式。

六、代码配置
-
主要初始化函数,方式一(使用ble_advertising_init和ble_advertising_conn_cfg_tag_set):
/**@brief Function for initializing the Advertising functionality.*/ static void advertising_init(void) {ret_code_t err_code;ble_advertising_init_t init;memset(&init, 0, sizeof(init));init.advdata.name_type = BLE_ADVDATA_FULL_NAME;init.advdata.include_appearance = true;init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);init.srdata.uuids_complete.p_uuids = m_adv_uuids;init.config.ble_adv_fast_enabled = true;init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;init.config.ble_adv_fast_timeout = APP_ADV_DURATION;init.evt_handler = on_adv_evt;err_code = ble_advertising_init(&m_advertising, &init);APP_ERROR_CHECK(err_code);ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); } -
方式二(可配置更多信息,提取了ble_advertising_init和ble_advertising_conn_cfg_tag_set内容来实现):
/**@brief Struct that contains pointers to the encoded advertising data. */ static ble_gap_adv_data_t m_adv_data = {.adv_data ={.p_data = m_enc_advdata,.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX},.scan_rsp_data ={.p_data = m_enc_scan_response_data,.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX} };static void advertising_init(void) {ret_code_t err_code;ble_advdata_t advdata;ble_advdata_t srdata;// Build and set advertising data.memset(&advdata, 0, sizeof(advdata));advdata.name_type = BLE_ADVDATA_FULL_NAME;advdata.include_appearance = true;advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;memset(&srdata, 0, sizeof(srdata));srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);srdata.uuids_complete.p_uuids = m_adv_uuids;err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);APP_ERROR_CHECK(err_code);err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);APP_ERROR_CHECK(err_code);ble_gap_adv_params_t adv_params;// Set advertising parameters.memset(&adv_params, 0, sizeof(adv_params));adv_params.primary_phy = BLE_GAP_PHY_1MBPS;adv_params.duration = APP_ADV_DURATION;adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;adv_params.p_peer_addr = NULL;adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;adv_params.interval = APP_ADV_INTERVAL;err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);APP_ERROR_CHECK(err_code); } -
可仿真查看广播实例m_advertising(IAR或MDK中),可以看到广播的数据内容:

- 空中抓包数据示例:

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
