赞
踩
因为笔者周围蓝牙设备过多,所以就不做直接连接实验了,但是仍就会先从直接连接讲。
想要连接设备,我们的主机要发起连接,但是发起之后,怎么进行连接,这个是由连接参数决定,这就又回到了设置扫描初始化那个结构体:
连接参数结构体定义:
- typedef struct
- {
- uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
- uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
- uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
- uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
- } ble_gap_conn_params_t;
参数意义可以参考以下文档的3.4节:
这里我们定义:
然后它被放在和扫描参数一起初始化:
然后只需要在扫描回调事件中连接:
- ret_code_t err_code;
-
- // 配置准备连接的设备MAC
- ble_gap_addr_t m_addr;
- m_addr.addr_id_peer = 1;
- m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
- memcpy(m_addr.addr,p_scan_evt->params.p_not_found->peer_addr.addr,BLE_GAP_ADDR_LEN);
-
- // 停止扫描
- nrf_ble_scan_stop();
- // 发起连接
- err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
- APP_ERROR_CHECK(err_code);
在直接连接的例子中,我们使用的是判断信号强度,然后直接把扫描到的设备的MAC地址复制到我们想要连接设备的地址里:
但是前文说过,笔者周围蓝牙设备太多,所以不做直接连接了,直接做过滤连接:
我把连接处理放在了,过滤匹配后的事件回调内,但没有删掉对信号强度的判断,也就是除了过滤要符合,信号还要够强。
注意,我们把扫描关闭后,就不再会有扫描事件被触发回调了,而到了BLE事件中:
- //******************************************************************
- // fn : ble_evt_handler
- //
- // brief : BLE事件回调
- // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP
- //
- // param : ble_evt_t 事件类型
- // p_context 未使用
- //
- // return : none
- static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
- {
- ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
- ble_gap_evt_connected_t const * p_connected_evt = &p_gap_evt->params.connected;
- switch (p_ble_evt->header.evt_id)
- {
- // 连接
- case BLE_GAP_EVT_CONNECTED:
- NRF_LOG_INFO("Connected. conn_DevAddr: %s\nConnected. conn_handle: 0x%04x\nConnected. conn_Param: %d,%d,%d,%d",
- Util_convertBdAddr2Str((uint8_t*)p_connected_evt->peer_addr.addr),
- p_gap_evt->conn_handle,
- p_connected_evt->conn_params.min_conn_interval,
- p_connected_evt->conn_params.max_conn_interval,
- p_connected_evt->conn_params.slave_latency,
- p_connected_evt->conn_params.conn_sup_timeout
- );
- break;
- // 断开连接
- case BLE_GAP_EVT_DISCONNECTED:
- NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%04x",
- p_gap_evt->conn_handle,
- p_gap_evt->params.disconnected.reason);
- // 如果需要异常断开重连,可以打开下面的注释
- // scan_start(); // 重新开始扫描
- break;
-
- default:
- break;
- }
- }
当设备连接和断开后,分别会触发:
BLE_GAP_EVT_CONNECTED 和 BLE_GAP_EVT_DISCONNECTED这两个事件,其他事件还有:
总的扫描回调函数:
-
- //******************************************************************
- // fn : scan_start
- //
- // brief : 开始扫描
- //
- // param : none
- //
- // return : none
- static void scan_start(void)
- {
- ret_code_t ret;
-
- ret = nrf_ble_scan_start(&m_scan);
- APP_ERROR_CHECK(ret);
- }
-
- //******************************************************************
- // fn : scan_evt_handler
- //
- // brief : 处理扫描回调事件
- //
- // param : scan_evt_t 扫描事件结构体
- //
- // return : none
- static void scan_evt_handler(scan_evt_t const * p_scan_evt)
- {
- uint32_t err_code;
- ble_gap_addr_t peer_addr;
- ble_gap_addr_t const * p_peer_addr;
- switch(p_scan_evt->scan_evt_id)
- {
- // 白名单设置请求
- case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
- {
- memset(&peer_addr, 0x00, sizeof(peer_addr));
- peer_addr.addr_id_peer = 1;
- peer_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
- peer_addr.addr[5] = 0xD0;
- peer_addr.addr[4] = 0xD3;
- peer_addr.addr[3] = 0x07;
- peer_addr.addr[2] = 0xCE;
- peer_addr.addr[1] = 0xDF;
- peer_addr.addr[0] = 0xF5;
- p_peer_addr = &peer_addr;
-
- // 设置白名单
- err_code = sd_ble_gap_whitelist_set(&p_peer_addr, 0x01);
- if (err_code == NRF_SUCCESS)
- {
- NRF_LOG_INFO("Successfully set whitelist!");
- }
- APP_ERROR_CHECK(err_code);
- }break;
-
- // 扫描到的白名单设备数据
- case NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT:
- {
- // 判断是否为扫描回调数据
- if(p_scan_evt->params.p_whitelist_adv_report->type.scan_response)
- {
- if(p_scan_evt->params.p_whitelist_adv_report->data.len) // 存在扫描回调数据
- {
- NRF_LOG_INFO("scan data: %s",
- Util_convertHex2Str(
- p_scan_evt->params.p_whitelist_adv_report->data.p_data,
- p_scan_evt->params.p_whitelist_adv_report->data.len));
- }
- else
- {
- NRF_LOG_INFO("scan data: %s","NONE");
- }
- NRF_LOG_INFO("rssi: %ddBm",p_scan_evt->params.p_whitelist_adv_report->rssi);
- }
- else // 否则为广播数据
- {
- // 打印扫描的设备MAC
- NRF_LOG_INFO("Device MAC: %s",
- Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.p_whitelist_adv_report->peer_addr.addr));
-
- if(p_scan_evt->params.p_whitelist_adv_report->data.len) // 存在广播数据
- {
- NRF_LOG_INFO("adv data: %s",
- Util_convertHex2Str(
- p_scan_evt->params.p_whitelist_adv_report->data.p_data,
- p_scan_evt->params.p_whitelist_adv_report->data.len));
- }
- else
- {
- NRF_LOG_INFO("adv data: %s","NONE");
- }
- }
- } break;
- case NRF_BLE_SCAN_EVT_NOT_FOUND:
- {
- NRF_LOG_INFO("@@@@@@@@@@@@-------------------------- EVENT ------------------------------");
- // 判断是否为扫描回调数据
- if(p_scan_evt->params.p_not_found->type.scan_response)
- {
- if(p_scan_evt->params.p_not_found->data.len) // 存在扫描回调数据
- {
- NRF_LOG_INFO("@@@@@@@@@@@@ScanRsp Data:%s",
- Util_convertHex2Str(
- p_scan_evt->params.p_not_found->data.p_data,
- p_scan_evt->params.p_not_found->data.len));
- }
- else
- {
- NRF_LOG_INFO("@@@@@@@@@@@@ScanRsp Data:%s","NONE");
- }
-
- }
- else // 否则为广播数据
- {
- //打印设备RSSI信号
- NRF_LOG_INFO("@@@@@@@@@@@@Device RSSI: %ddBm",p_scan_evt->params.p_not_found->rssi);
- // 打印扫描的设备MAC
- NRF_LOG_INFO("@@@@@@@@@@@@Device MAC: %s",
- Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.p_not_found->peer_addr.addr));
-
- if(p_scan_evt->params.p_not_found->data.len) // 存在广播数据
- {
- NRF_LOG_INFO("@@@@@@@@@@@@Adv Data: %s",
- Util_convertHex2Str(
- p_scan_evt->params.p_not_found->data.p_data,
- p_scan_evt->params.p_not_found->data.len));
- }
- else
- {
- NRF_LOG_INFO("@@@@@@@@@@@@Adv Data: %s","NONE");
- }
- }
- 如果扫描到的设备信号强度大于-30dBm
- //if(p_scan_evt->params.p_not_found->rssi > (-30))
- //{
- // ret_code_t err_code;
-
- // // 配置准备连接的设备MAC
- // ble_gap_addr_t m_addr;
- // m_addr.addr_id_peer = 1;
- // m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
- // memcpy(m_addr.addr,p_scan_evt->params.p_not_found->peer_addr.addr,BLE_GAP_ADDR_LEN);
-
- // // 停止扫描
- // nrf_ble_scan_stop();
- // // 发起连接
- // err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
- // APP_ERROR_CHECK(err_code);
- //}
-
- } break;
- case NRF_BLE_SCAN_EVT_FILTER_MATCH:
- {
- // 下面这一段我们只保留了扫描回调数据获取的部分,因为从机筛选广播的UUID在扫描回调数据
- // 判断是否为扫描回调数据
- if(p_scan_evt->params.filter_match.p_adv_report->type.scan_response)
- {
- NRF_LOG_INFO("Device MAC: %s",
- Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
-
- if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在扫描回调数据
- {
- NRF_LOG_INFO("ScanRsp Data:%s",
- Util_convertHex2Str(
- p_scan_evt->params.filter_match.p_adv_report->data.p_data,
- p_scan_evt->params.filter_match.p_adv_report->data.len));
- }
- else
- {
- NRF_LOG_INFO("ScanRsp Data:%s","NONE");
- }
- NRF_LOG_INFO("Device RSSI: %ddBm",p_scan_evt->params.filter_match.p_adv_report->rssi);
- }
- // 如果扫描到的设备信号强度大于-30dBm
- if(p_scan_evt->params.filter_match.p_adv_report->rssi > (-30))
- {
- ret_code_t err_code;
-
- // 配置准备连接的设备MAC
- ble_gap_addr_t m_addr;
- m_addr.addr_id_peer = 1;
- m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
- memcpy(m_addr.addr,p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr,BLE_GAP_ADDR_LEN);
-
- // 停止扫描
- nrf_ble_scan_stop();
- // 发起连接
- err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
- APP_ERROR_CHECK(err_code);
- }
- // else // 否则为广播数据
- // {
- // // 打印扫描的设备MAC
- // NRF_LOG_INFO("Device MAC: %s",
- // Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
- //
- // if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在广播数据
- // {
- // NRF_LOG_INFO("adv data: %s",
- // Util_convertHex2Str(
- // p_scan_evt->params.filter_match.p_adv_report->data.p_data,
- // p_scan_evt->params.filter_match.p_adv_report->data.len));
- // }
- // else
- // {
- // NRF_LOG_INFO("adv data: %s","NONE");
- // }
- // }
- } break;
- default:
- break;
- }
- }
从机主要就在蓝牙事件回调中添加了对连接断开事件的处理,和主机端一样:
- //******************************************************************
- // fn : ble_evt_handler
- //
- // brief : BLE事件回调
- // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP
- //
- // param : ble_evt_t 事件类型
- // p_context 未使用
- //
- // return : none
- static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
- {
- ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
- ble_gap_evt_connected_t const * p_connected_evt = &p_gap_evt->params.connected;
- switch (p_ble_evt->header.evt_id)
- {
- // 连接
- case BLE_GAP_EVT_CONNECTED:
- NRF_LOG_INFO("Connected. conn_DevAddr: %s\nConnected. conn_handle: 0x%04x\nConnected. conn_Param: %d,%d,%d,%d",
- Util_convertBdAddr2Str((uint8_t*)p_connected_evt->peer_addr.addr),
- p_gap_evt->conn_handle,
- p_connected_evt->conn_params.min_conn_interval,
- p_connected_evt->conn_params.max_conn_interval,
- p_connected_evt->conn_params.slave_latency,
- p_connected_evt->conn_params.conn_sup_timeout
- );
- break;
- // 断开连接
- case BLE_GAP_EVT_DISCONNECTED:
- NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%04x",
- p_gap_evt->conn_handle,
- p_gap_evt->params.disconnected.reason);
- break;
-
- default:
- // No implementation needed.
- break;
- }
- }
注意这个回调的参数:
- /**@brief Common BLE Event type, wrapping the module specific event reports. */
- typedef struct
- {
- ble_evt_hdr_t header; /**< Event header. */
- union
- {
- ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */
- ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */
- ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */
- ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */
- ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */
- } evt; /**< Event union. */
- } ble_evt_t;
可以看到,ble事件中,有:
普通事件、gap事件、gatt客户端事件、gatt服务端事件、l2cap事件
而gap事件中包含连接和断开:
而每个结构体里包含该事件所能获取到的信息,就比如连接事件中:
我们可以获取,对方的地址、角色(中心或外围设备)、连接参数等。
主机端打印:
从机端打印:
这里主要更改的是主机端,我们不再需要提供MAC地址去连接对应的设备,而是使用自动连接:
这个参数我们之前就看到过,只不过没有做讲解,也没有设置它:
然后我们把之前在 NRF_BLE_SCAN_EVT_FILTER_MATCH 中手动连接的代码注释掉,添加两个事件回调:
和上文相同,略。
可以看到,在扫描到符合过滤设置后,设备直接被连接上了。
同样的道理,我们只需要在以前白名单扫描模式的基础上,开启自动连接就可以了:
这部分代码和之前基本上一模一样,完全可以举一反三。
略。
完全与预期相符。
不再赘述,和前面一模一样,只是回调函数里面放个手动连接而已:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。