Professional Documents
Culture Documents
蓝⽛牙共存说明
!
版本 1.0
版权 © 2018
关于本⼿手册
本⽂文档为 ESP32 BT&BLE 双模蓝⽛牙共存说明。
发布说明
⽇日期 版本 发布说明
⽂文档变更更通知
⽤用户可通过乐鑫官⽹网订阅技术⽂文档变更更的电⼦子邮件通知。
证书下载
⽤用户可通过乐鑫官⽹网下载产品证书。
⽬目录
1. BT&BLE 共存结构图 ............................................................................................................... 1
2. 流程说明 .................................................................................................................................2
3. 代码说明 .................................................................................................................................4
3.2. 连接 ..........................................................................................................................................10
1. BT&BLE 共存结构图
Espressif ! /12
1 2018.02
2.流程说明
!
2. 流程说明
2.1. 初始化流程
DEV_A 上电后将初始化 BT SPP initiator 和 BLE GATT client 功能。初始化完成后,开始查
找经典蓝⽛牙 (SPP) 设备,找到设备后进⾏行行连接。SPP 连接完成后开始搜索 BLE ⼴广播,搜
索到设备后进⾏行行连接。DEV_A 配置如下图 2-1 所示。
!
图 2-1. DEV_A 配置界⾯面
!
图 2-2. DEV_B 配置界⾯面
⚠ 注意:
Espressif ! /12
2 2018.02
2.流程说明
!
2.2. ⼴广播说明
经典蓝⽛牙 inquiry scan 时的设备名称(EIR 中)与 BLE ⼴广播时的设备名称可以是同⼀一个名
称,也可以是不不同名称。若需区分两者的设备名称,BLE 可以使⽤用
esp_ble_gap_config_adv_data_raw() 函数,⼴广播特定的蓝⽛牙设备名称。
2.3. 连接流程
DEV_B 初始化完成后会⾃自动进⼊入 BT inquiry scan 状态,并且进⾏行行 BLE ⼴广播,DEV_A 的
BT SPP initiator 搜索到对应设备后进⾏行行连接,然后再开始搜索 BLE 设备,搜索到设备后
进⾏行行连接。DEV_A 和 DEV_B 之间的通信,请⻅见图 2-3。
!
图 2-3. DEV_A 和 DEV_B 测试流程图
Espressif ! /12
3 2018.02
3. 代码说明
!
3. 代码说明
3.1. 初始化
3.1.1. 初始化流程
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
ESP_ERROR_CHECK( ret );
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
return;
ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
if (ret) {
return;
⚠ 注意:
ret = esp_bluedroid_init();
if (ret) {
return;
ret = esp_bluedroid_enable();
if (ret) {
return;
Espressif ! /12
4 2018.02
3. 代码说明
!
• bt_spp_init()
• ble_gatts_init()
具体代码如下:
void bt_spp_init(void)
if (ret) {
return;
ret = esp_spp_init(esp_spp_mode);
if (ret) {
return;
switch (event) {
case ESP_SPP_INIT_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_INIT_EVT\n");
esp_bt_dev_set_device_name(BT_DEVICE_NAME);
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
esp_spp_start_srv(sec_mask,role_slave, 0, SPP_SERVER_NAME);
break;
case ESP_SPP_DISCOVERY_COMP_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_DISCOVERY_COMP_EVT\n");
break;
case ESP_SPP_OPEN_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_OPEN_EVT\n");
break;
case ESP_SPP_CLOSE_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_CLOSE_EVT\n");
break;
case ESP_SPP_START_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_START_EVT\n");
break;
case ESP_SPP_CL_INIT_EVT:
Espressif ! /12
5 2018.02
3. 代码说明
!
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_CL_INIT_EVT\n");
break;
case ESP_SPP_DATA_IND_EVT:
param->data_ind.len, param->data_ind.handle);
esp_log_buffer_hex("",param->data_ind.data,param->data_ind.len);
#else
gettimeofday(&time_new, NULL);
data_num += param->data_ind.len;
print_speed();
#endif
break;
case ESP_SPP_CONG_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_CONG_EVT\n");
break;
case ESP_SPP_WRITE_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_WRITE_EVT\n");
break;
case ESP_SPP_SRV_OPEN_EVT:
ESP_LOGI(BT_SPP_TAG, "ESP_SPP_SRV_OPEN_EVT\n");
gettimeofday(&time_old, NULL);
break;
default:
break;
if (ret){
return;
ret = esp_ble_gap_register_callback(gap_event_handler);
if (ret){
return;
ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID);
if (ret){
return;
ret = esp_ble_gatts_app_register(PROFILE_B_APP_ID);
if (ret){
Espressif ! /12
6 2018.02
3. 代码说明
!
return;
if (local_mtu_ret){
gatts_semaphore = xSemaphoreCreateMutex();
if (!gatts_semaphore) {
return;
⚠ 注意:
• bt_spp_init();
• ble_gattc_init()
具体代码如下:
void bt_spp_init(void)
if (ret) {
return;
ret = esp_spp_register_callback(esp_spp_cb);
if (ret) {
return;
ret = esp_spp_init(esp_spp_mode);
if (ret) {
return;
switch(event){
Espressif ! /12
7 2018.02
3. 代码说明
!
case ESP_BT_GAP_DISC_RES_EVT:
ESP_LOGI(SPP_TAG, "ESP_BT_GAP_DISC_RES_EVT");
if (param->disc_res.prop[i].type == ESP_BT_GAP_DEV_PROP_EIR
if (strlen(remote_spp_name) == peer_bdname_len
esp_spp_start_discovery(peer_bd_addr);
esp_bt_gap_cancel_discovery();
break;
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
ESP_LOGI(SPP_TAG, "ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
break;
case ESP_BT_GAP_RMT_SRVCS_EVT:
ESP_LOGI(SPP_TAG, "ESP_BT_GAP_RMT_SRVCS_EVT");
break;
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
ESP_LOGI(SPP_TAG, "ESP_BT_GAP_RMT_SRVC_REC_EVT");
break;
default:
break;
switch (event) {
case ESP_SPP_INIT_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_INIT_EVT");
esp_bt_dev_set_device_name(EXCAMPLE_DEVICE_NAME);
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
break;
case ESP_SPP_DISCOVERY_COMP_EVT:
if (param->disc_comp.status == ESP_SPP_SUCCESS) {
break;
case ESP_SPP_OPEN_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_OPEN_EVT");
//BLE 开始扫描
Espressif ! /12
8 2018.02
3. 代码说明
!
esp_ble_gap_start_scanning(duration);
gettimeofday(&time_old, NULL);
break;
case ESP_SPP_CLOSE_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_CLOSE_EVT");
break;
case ESP_SPP_START_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_START_EVT");
break;
case ESP_SPP_CL_INIT_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_CL_INIT_EVT");
break;
case ESP_SPP_DATA_IND_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_DATA_IND_EVT");
break;
case ESP_SPP_CONG_EVT:
#endif
if (param->cong.cong == 0) {
break;
case ESP_SPP_WRITE_EVT:
esp_log_buffer_hex("",spp_data,SPP_DATA_LEN);
#else
gettimeofday(&time_new, NULL);
data_num += param->write.len;
print_speed();
#endif
if (param->write.cong == 0) {
break;
case ESP_SPP_SRV_OPEN_EVT:
ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT");
break;
default:
break;
Espressif ! /12
9 2018.02
3. 代码说明
!
if (ret){
ESP_LOGE(GATTC_TAG, "%s gap register failed, error code = %x\n", __func__, ret);
return;
ret = esp_ble_gattc_register_callback(esp_gattc_cb);
if(ret){
ESP_LOGE(GATTC_TAG, "%s gattc register failed, error code = %x\n", __func__, ret);
return;
ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID);
if (ret){
ESP_LOGE(GATTC_TAG, "%s gattc app register failed, error code = %x\n", __func__,
ret);
if (local_mtu_ret){
⚠ 注意:
3.2. 连接
DEV_A 在完成初始化后,开始搜索经典蓝⽛牙设备,搜索到设备后会在 esp_bt_gap_cb 函
数中回调 ESP_BT_GAP_DISC_RES_EVT,符合条件后调⽤用
esp_spp_start_discovery(peer_bd_addr) 连接设备。设备连接成功后会在 esp_spp_cb
函数中回调 ESP_SPP_OPEN_EVT,在此事件中开始发送 SPP 数据,计算 SPP 速率,并
开始搜索 BLE 设备。
Espressif ! /12
10 2018.02
3. 代码说明
!
3.3. 数据发送与接收
DEV_A SPP 连接以后使⽤用 esp_spp_write() 函数发送 SPP 数据并计算速率。
3.4. 性能说明
BT SPP 和 BLE 连接成功以后会⾃自动发送数据,计算吞吐率。单独运⾏行行 BT SPP 的速率为
230 KB/s 左右,单独运⾏行行 BLE 的速率为 40 KB/s 左右(优化后有 90 KB/s)。⽬目前,在
BLE 中仅计算了了 GATT notification 的速率,使⽤用当前的参数速率 BT SPP 120 KB/s、BLE
GATT notification 30 KB/s 左右,BT SPP 和 BLE GATT notification 的速率是可调的。具体
可以通过调节 BLE 的连接参数,发送 GATT notification 的⻓长度和频率调整。SPP 和 GATT
的吞吐量量 log,请⻅见图 3-1。
Espressif ! /12
11 2018.02
免责申明和版权公告
本⽂文中的信息,包括供参考的 URL 地址,如有变更更,恕不不另⾏行行通知。
⽂文档“按现状”提供,不不负任何担保责任,包括对适销性、适⽤用于特定⽤用途或⾮非侵
权性的任何担保,和任何提案、规格或样品在他处提到的任何担保。本⽂文档不不
负任何责任,包括使⽤用本⽂文档内信息产⽣生的侵犯任何专利利权⾏行行为的责任。本⽂文
档在此未以禁⽌止反⾔言或其他⽅方式授予任何知识产权使⽤用许可,不不管是明示许可
还是暗示许可。
Wi-Fi 联盟成员标志归 Wi-Fi 联盟所有。蓝⽛牙标志是 Bluetooth SIG 的注册商
标。
⽂文中提到的所有商标名称、商标和注册商标均属其各⾃自所有者的财产,特此声
乐鑫 IoT 团队
明。
www.espressif.com 版权归 © 2018 乐鑫所有。保留留所有权利利。