当前位置:   article > 正文

从零开始的nrf52832蓝牙开发(8)--连接_ble_gap_addr_t

ble_gap_addr_t

因为笔者周围蓝牙设备过多,所以就不做直接连接实验了,但是仍就会先从直接连接讲。

1.过滤连接

1.1主机端

想要连接设备,我们的主机要发起连接,但是发起之后,怎么进行连接,这个是由连接参数决定,这就又回到了设置扫描初始化那个结构体:

连接参数结构体定义

  1. typedef struct
  2. {
  3. uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
  4. uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
  5. uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
  6. uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
  7. } ble_gap_conn_params_t;

参数意义可以参考以下文档的3.4节:

蓝牙技术详解

这里我们定义:

然后它被放在和扫描参数一起初始化:

 

然后只需要在扫描回调事件中连接:

  1. ret_code_t err_code;
  2. // 配置准备连接的设备MAC
  3. ble_gap_addr_t m_addr;
  4. m_addr.addr_id_peer = 1;
  5. m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
  6. memcpy(m_addr.addr,p_scan_evt->params.p_not_found->peer_addr.addr,BLE_GAP_ADDR_LEN);
  7. // 停止扫描
  8. nrf_ble_scan_stop();
  9. // 发起连接
  10. err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
  11. APP_ERROR_CHECK(err_code);

在直接连接的例子中,我们使用的是判断信号强度,然后直接把扫描到的设备的MAC地址复制到我们想要连接设备的地址里:

 

但是前文说过,笔者周围蓝牙设备太多,所以不做直接连接了,直接做过滤连接:

 

我把连接处理放在了,过滤匹配后的事件回调内,但没有删掉对信号强度的判断,也就是除了过滤要符合,信号还要够强。

注意,我们把扫描关闭后,就不再会有扫描事件被触发回调了,而到了BLE事件中:

  1. //******************************************************************
  2. // fn : ble_evt_handler
  3. //
  4. // brief : BLE事件回调
  5. // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP
  6. //
  7. // param : ble_evt_t 事件类型
  8. // p_context 未使用
  9. //
  10. // return : none
  11. static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
  12. {
  13. ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
  14. ble_gap_evt_connected_t const * p_connected_evt = &p_gap_evt->params.connected;
  15. switch (p_ble_evt->header.evt_id)
  16. {
  17. // 连接
  18. case BLE_GAP_EVT_CONNECTED:
  19. NRF_LOG_INFO("Connected. conn_DevAddr: %s\nConnected. conn_handle: 0x%04x\nConnected. conn_Param: %d,%d,%d,%d",
  20. Util_convertBdAddr2Str((uint8_t*)p_connected_evt->peer_addr.addr),
  21. p_gap_evt->conn_handle,
  22. p_connected_evt->conn_params.min_conn_interval,
  23. p_connected_evt->conn_params.max_conn_interval,
  24. p_connected_evt->conn_params.slave_latency,
  25. p_connected_evt->conn_params.conn_sup_timeout
  26. );
  27. break;
  28. // 断开连接
  29. case BLE_GAP_EVT_DISCONNECTED:
  30. NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%04x",
  31. p_gap_evt->conn_handle,
  32. p_gap_evt->params.disconnected.reason);
  33. // 如果需要异常断开重连,可以打开下面的注释
  34. // scan_start(); // 重新开始扫描
  35. break;
  36. default:
  37. break;
  38. }
  39. }

当设备连接和断开后,分别会触发:

BLE_GAP_EVT_CONNECTED 和 BLE_GAP_EVT_DISCONNECTED这两个事件,其他事件还有:

 

总的扫描回调函数:

  1. //******************************************************************
  2. // fn : scan_start
  3. //
  4. // brief : 开始扫描
  5. //
  6. // param : none
  7. //
  8. // return : none
  9. static void scan_start(void)
  10. {
  11. ret_code_t ret;
  12. ret = nrf_ble_scan_start(&m_scan);
  13. APP_ERROR_CHECK(ret);
  14. }
  15. //******************************************************************
  16. // fn : scan_evt_handler
  17. //
  18. // brief : 处理扫描回调事件
  19. //
  20. // param : scan_evt_t 扫描事件结构体
  21. //
  22. // return : none
  23. static void scan_evt_handler(scan_evt_t const * p_scan_evt)
  24. {
  25. uint32_t err_code;
  26. ble_gap_addr_t peer_addr;
  27. ble_gap_addr_t const * p_peer_addr;
  28. switch(p_scan_evt->scan_evt_id)
  29. {
  30. // 白名单设置请求
  31. case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
  32. {
  33. memset(&peer_addr, 0x00, sizeof(peer_addr));
  34. peer_addr.addr_id_peer = 1;
  35. peer_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
  36. peer_addr.addr[5] = 0xD0;
  37. peer_addr.addr[4] = 0xD3;
  38. peer_addr.addr[3] = 0x07;
  39. peer_addr.addr[2] = 0xCE;
  40. peer_addr.addr[1] = 0xDF;
  41. peer_addr.addr[0] = 0xF5;
  42. p_peer_addr = &peer_addr;
  43. // 设置白名单
  44. err_code = sd_ble_gap_whitelist_set(&p_peer_addr, 0x01);
  45. if (err_code == NRF_SUCCESS)
  46. {
  47. NRF_LOG_INFO("Successfully set whitelist!");
  48. }
  49. APP_ERROR_CHECK(err_code);
  50. }break;
  51. // 扫描到的白名单设备数据
  52. case NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT:
  53. {
  54. // 判断是否为扫描回调数据
  55. if(p_scan_evt->params.p_whitelist_adv_report->type.scan_response)
  56. {
  57. if(p_scan_evt->params.p_whitelist_adv_report->data.len) // 存在扫描回调数据
  58. {
  59. NRF_LOG_INFO("scan data: %s",
  60. Util_convertHex2Str(
  61. p_scan_evt->params.p_whitelist_adv_report->data.p_data,
  62. p_scan_evt->params.p_whitelist_adv_report->data.len));
  63. }
  64. else
  65. {
  66. NRF_LOG_INFO("scan data: %s","NONE");
  67. }
  68. NRF_LOG_INFO("rssi: %ddBm",p_scan_evt->params.p_whitelist_adv_report->rssi);
  69. }
  70. else // 否则为广播数据
  71. {
  72. // 打印扫描的设备MAC
  73. NRF_LOG_INFO("Device MAC: %s",
  74. Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.p_whitelist_adv_report->peer_addr.addr));
  75. if(p_scan_evt->params.p_whitelist_adv_report->data.len) // 存在广播数据
  76. {
  77. NRF_LOG_INFO("adv data: %s",
  78. Util_convertHex2Str(
  79. p_scan_evt->params.p_whitelist_adv_report->data.p_data,
  80. p_scan_evt->params.p_whitelist_adv_report->data.len));
  81. }
  82. else
  83. {
  84. NRF_LOG_INFO("adv data: %s","NONE");
  85. }
  86. }
  87. } break;
  88. case NRF_BLE_SCAN_EVT_NOT_FOUND:
  89. {
  90. NRF_LOG_INFO("@@@@@@@@@@@@-------------------------- EVENT ------------------------------");
  91. // 判断是否为扫描回调数据
  92. if(p_scan_evt->params.p_not_found->type.scan_response)
  93. {
  94. if(p_scan_evt->params.p_not_found->data.len) // 存在扫描回调数据
  95. {
  96. NRF_LOG_INFO("@@@@@@@@@@@@ScanRsp Data:%s",
  97. Util_convertHex2Str(
  98. p_scan_evt->params.p_not_found->data.p_data,
  99. p_scan_evt->params.p_not_found->data.len));
  100. }
  101. else
  102. {
  103. NRF_LOG_INFO("@@@@@@@@@@@@ScanRsp Data:%s","NONE");
  104. }
  105. }
  106. else // 否则为广播数据
  107. {
  108. //打印设备RSSI信号
  109. NRF_LOG_INFO("@@@@@@@@@@@@Device RSSI: %ddBm",p_scan_evt->params.p_not_found->rssi);
  110. // 打印扫描的设备MAC
  111. NRF_LOG_INFO("@@@@@@@@@@@@Device MAC: %s",
  112. Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.p_not_found->peer_addr.addr));
  113. if(p_scan_evt->params.p_not_found->data.len) // 存在广播数据
  114. {
  115. NRF_LOG_INFO("@@@@@@@@@@@@Adv Data: %s",
  116. Util_convertHex2Str(
  117. p_scan_evt->params.p_not_found->data.p_data,
  118. p_scan_evt->params.p_not_found->data.len));
  119. }
  120. else
  121. {
  122. NRF_LOG_INFO("@@@@@@@@@@@@Adv Data: %s","NONE");
  123. }
  124. }
  125. 如果扫描到的设备信号强度大于-30dBm
  126. //if(p_scan_evt->params.p_not_found->rssi > (-30))
  127. //{
  128. // ret_code_t err_code;
  129. // // 配置准备连接的设备MAC
  130. // ble_gap_addr_t m_addr;
  131. // m_addr.addr_id_peer = 1;
  132. // m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
  133. // memcpy(m_addr.addr,p_scan_evt->params.p_not_found->peer_addr.addr,BLE_GAP_ADDR_LEN);
  134. // // 停止扫描
  135. // nrf_ble_scan_stop();
  136. // // 发起连接
  137. // err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
  138. // APP_ERROR_CHECK(err_code);
  139. //}
  140. } break;
  141. case NRF_BLE_SCAN_EVT_FILTER_MATCH:
  142. {
  143. // 下面这一段我们只保留了扫描回调数据获取的部分,因为从机筛选广播的UUID在扫描回调数据
  144. // 判断是否为扫描回调数据
  145. if(p_scan_evt->params.filter_match.p_adv_report->type.scan_response)
  146. {
  147. NRF_LOG_INFO("Device MAC: %s",
  148. Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
  149. if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在扫描回调数据
  150. {
  151. NRF_LOG_INFO("ScanRsp Data:%s",
  152. Util_convertHex2Str(
  153. p_scan_evt->params.filter_match.p_adv_report->data.p_data,
  154. p_scan_evt->params.filter_match.p_adv_report->data.len));
  155. }
  156. else
  157. {
  158. NRF_LOG_INFO("ScanRsp Data:%s","NONE");
  159. }
  160. NRF_LOG_INFO("Device RSSI: %ddBm",p_scan_evt->params.filter_match.p_adv_report->rssi);
  161. }
  162. // 如果扫描到的设备信号强度大于-30dBm
  163. if(p_scan_evt->params.filter_match.p_adv_report->rssi > (-30))
  164. {
  165. ret_code_t err_code;
  166. // 配置准备连接的设备MAC
  167. ble_gap_addr_t m_addr;
  168. m_addr.addr_id_peer = 1;
  169. m_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
  170. memcpy(m_addr.addr,p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr,BLE_GAP_ADDR_LEN);
  171. // 停止扫描
  172. nrf_ble_scan_stop();
  173. // 发起连接
  174. err_code = sd_ble_gap_connect(&m_addr,&m_scan_params,&m_conn_params,APP_BLE_CONN_CFG_TAG);
  175. APP_ERROR_CHECK(err_code);
  176. }
  177. // else // 否则为广播数据
  178. // {
  179. // // 打印扫描的设备MAC
  180. // NRF_LOG_INFO("Device MAC: %s",
  181. // Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
  182. //
  183. // if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在广播数据
  184. // {
  185. // NRF_LOG_INFO("adv data: %s",
  186. // Util_convertHex2Str(
  187. // p_scan_evt->params.filter_match.p_adv_report->data.p_data,
  188. // p_scan_evt->params.filter_match.p_adv_report->data.len));
  189. // }
  190. // else
  191. // {
  192. // NRF_LOG_INFO("adv data: %s","NONE");
  193. // }
  194. // }
  195. } break;
  196. default:
  197. break;
  198. }
  199. }

 

1.2从机端

从机主要就在蓝牙事件回调中添加了对连接断开事件的处理,和主机端一样:

  1. //******************************************************************
  2. // fn : ble_evt_handler
  3. //
  4. // brief : BLE事件回调
  5. // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP
  6. //
  7. // param : ble_evt_t 事件类型
  8. // p_context 未使用
  9. //
  10. // return : none
  11. static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
  12. {
  13. ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
  14. ble_gap_evt_connected_t const * p_connected_evt = &p_gap_evt->params.connected;
  15. switch (p_ble_evt->header.evt_id)
  16. {
  17. // 连接
  18. case BLE_GAP_EVT_CONNECTED:
  19. NRF_LOG_INFO("Connected. conn_DevAddr: %s\nConnected. conn_handle: 0x%04x\nConnected. conn_Param: %d,%d,%d,%d",
  20. Util_convertBdAddr2Str((uint8_t*)p_connected_evt->peer_addr.addr),
  21. p_gap_evt->conn_handle,
  22. p_connected_evt->conn_params.min_conn_interval,
  23. p_connected_evt->conn_params.max_conn_interval,
  24. p_connected_evt->conn_params.slave_latency,
  25. p_connected_evt->conn_params.conn_sup_timeout
  26. );
  27. break;
  28. // 断开连接
  29. case BLE_GAP_EVT_DISCONNECTED:
  30. NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%04x",
  31. p_gap_evt->conn_handle,
  32. p_gap_evt->params.disconnected.reason);
  33. break;
  34. default:
  35. // No implementation needed.
  36. break;
  37. }
  38. }

 注意这个回调的参数:

  1. /**@brief Common BLE Event type, wrapping the module specific event reports. */
  2. typedef struct
  3. {
  4. ble_evt_hdr_t header; /**< Event header. */
  5. union
  6. {
  7. ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */
  8. ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */
  9. ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */
  10. ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */
  11. ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */
  12. } evt; /**< Event union. */
  13. } ble_evt_t;

可以看到,ble事件中,有:

普通事件、gap事件、gatt客户端事件、gatt服务端事件、l2cap事件

而gap事件中包含连接和断开:

 

而每个结构体里包含该事件所能获取到的信息,就比如连接事件中:

 

 我们可以获取,对方的地址、角色(中心或外围设备)、连接参数等。

1.3实际现象

主机端打印:

 从机端打印:

2.过滤自动连接

2.1主机端

这里主要更改的是主机端,我们不再需要提供MAC地址去连接对应的设备,而是使用自动连接:

这个参数我们之前就看到过,只不过没有做讲解,也没有设置它:

 

然后我们把之前在 NRF_BLE_SCAN_EVT_FILTER_MATCH 中手动连接的代码注释掉,添加两个事件回调:

 

2.2从机端

和上文相同,略。

2.3实际现象

 

 可以看到,在扫描到符合过滤设置后,设备直接被连接上了。

3. 白名单自动连接

3.1主机端

同样的道理,我们只需要在以前白名单扫描模式的基础上,开启自动连接就可以了:

 

 

这部分代码和之前基本上一模一样,完全可以举一反三。

3.2从机

略。

3.3实验现象

 

完全与预期相符。

4.白名单手动连接

不再赘述,和前面一模一样,只是回调函数里面放个手动连接而已:

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号