NRF52840一主机多从机连接的代码解析

lgy198612RF/无线 2023-11-28 13:15:09 3095阅读 举报

一、简介

由于蓝牙主机和从机组网,如果不使用 Mesh 的话,只能组微微网。蓝牙5.0的微微网最大可以连接20个从机。

1.1 连接句柄

在主机与从机发生连接的时候会进行连接句柄的分配。连接句柄的作用是在蓝牙数据进行分组的时候进行设备区分的。连接句柄相当于一个“令牌”,从设备一旦和主设备发生连接,主设备就给从设备分配一个“令牌”。主设备通过这个“令牌”来识别与区分从设备。因此对于连接句柄的分配将是实现一主多从连接,并且进行通信的关键。

二、ble_app_multilink_central

打开工程 不同SDK\examples\ble_central\ble_app_multilink_central

2.1 main

2.2 buttons_init

在按键操作里,有一主多从发送数据的操作,可先不看这里。

2.2.1 button_event_handler

2.2.2 led_status_send_to_all

遍历所有从机,给从机发送 LED 灯亮灭命令

2.3 ble_stack_init

ble_stack_init() 协议栈初始化函数基本结构没有变化,设备变化的地方有下面几个地方:

2.3.1 nrf_sdh_ble_default_cfg_set

定义了可以连接的从机最大数量为8

2.3.2 ble_evt_handler

ble协议栈的回调函数,看下其中对于连接和断开等GAP状态的处理。

BLE_GAP_EVT_CONNECTED 连接状态,我们首先调用 ble_nus_c_handles_assign 函数去分配句柄,但实际上由于第三个参数为NULL,这里我们等于是给nus服务句柄置0。接下来我们调用 ble_db_discovery_start 函数去发现服务(由于有多个连接,所以我们需要根据当前连接的设备句柄参数去发现服务),成功发现NUS服务之后,会给我们在 ble_nus_c_evt_handler 回调函数中返回 BLE_NUS_C_EVT_DISCOVERY_COMPLETE 事件。




BLE_GAP_EVT_DISCONNECTED 断开状态,先判断了是否有设备连接,并且在最后重新开启扫描。

2.4 scan_start

在主函数中初始化完成后就会调用 scan_start() 开始监听从机的 BLE 广播。每当监听到 BLE 广播时,协议栈就会给上层应用一个广播事件,该事件由 NRF_SDH_BLE_OBSERVER 观察者递交给 ble_evt_handler 函数。

在 ble_evt_handler() 函数中添加 BLE_GAP_EVT_ADV_REPORT 事件,如果发现了从机广播,则产生 BLE_GAP_EVT_ADV_REPORT 事件,也就是广播报告,那么久调用 on_adv_report() 函数解析广播。


/**@brief Function for handling the advertising report BLE event.
 *
 * @param[in] p_adv_report  Advertising report from the SoftDevice.
 */
static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
{ 
  ret_code_t err_code;
  if (ble_advdata_name_find(p_adv_report->data.p_data,
                            p_adv_report->data.len,
                            m_target_periph_ame))// 发现指定名称的设备
  {
    // 对指定参数进行连接
    err_code = sd_ble_gap_connect(&p_adv_report->peer_addr,
                                  &m_scan_params,
                                  &m_connection_param,
                                  APP_BLE_CONN_CFG_TAG);
    if (err_code != NRF_SUCCESS)
    {
      NRF_LOG_ERROR("Connection Request Failed, reason %d", err_code);
    }
  }
  else
  {
    err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);// 如果没发现继续扫描
  }
}
1234567891011121314151617181920212223242526
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

通过 ble_advdata_name_find 函数发现指定广播名称的广播数据,如果是的话,则通过 sd_ble_gap_connect 函数对目标发起 GAP 连接。

这样主机设备就可以判断哪个设备是我们需要连接的从机了,所以主机程序和从机程序中,广播名称都要设置为:Nordic_Blinky

三、主机设备通知使能

3.1 lbs_c_init

不同于从机设备的多路连接(因为从机自己提供服务,服务是唯一的),主机连接的多个从机有可能存在服务的不同,所以我们需要初始化多个 m_lbs_c 的实例。 同样的在 lbs_c_init 的初始化函数中,我们需要对这些 m_lbs_c 的实例都进行初始化操作。
BLE_LBS_C_ARRAY_DEF(m_lbs_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT); /**< LED button client instances. */

3.2 ble_lbs_c_init

通过 ble_lbs_c_init 函数实现主机初始化,这个函数是一个数据结构体类型,通过 i 的不同值,来分别代表不同的从机链路。这个函数被称为客户端处理事件初始化函数。首先设置一个基础 UUID,这个基础 UUID 通过协议栈函数 sd_ble_uuid_vs_add 赋值给主设备。然后通过调用注册函数 ble_db_discovery_evt_register 通过 UUID 查出对应的服务。如果基础 UUID 相同,则会启动里面的回调函数 db_discovery_evt_handler 进行操作。

3.3 lbs_c_evt_handler

当发现主服务完成后 BLE_LBS_C_EVT_DISCOVERY_COMPLETE,启动主机使能从机的通知。

3.3.1 ble_lbs_c_button_notif_enable

进入按键通知使能服务 ble_lbs_c_button_notif_enable 函数内部,使能通知实际上就是 CCCD 的写操作,实际上就是通过协议栈函数 sd_ble_gattc_write 来实现 CCCD 的写入

3.3.2 cccd_configure

3.3.3 tx_buffer_process

四、主机设备接收从机数据

4.1 ble_lbs_c_on_ble_evt

当通知使能后,主机就可以接收从机发来的通知信息,一旦从机使用 hvx 通知函数上传数据给主机,主机就会收到数据,此时就会触发 BLE_GATTC_EVT_HVX 事件

4.2 on_hvx

on_hvx 函数最终处理接收到的从机通知数据,触发数据类型为按键通知 BLE_LBS_C_EVT_BUTTON_NOTIFICATION ,操作句柄为 p_ble_lbs_c->conn_handle,数据存 ble_lbs_c_evt.params.button.button_state 中

4.3 lbs_c_evt_handler

一旦触发了蓝牙事件 BLE_LBS_C_EVT_BUTTON_NOTIFICATION,在蓝牙事件回调函数 lbs_c_evt_handler 中,根据不同的 p_lbs_c_evt->conn_handle 决定不同的从机链路,来点亮哪个LED灯。

五、主机设备数据写从机5.1 ble_lbs_led_status_send

把主机按键状态作为数据写入到从机,通过 i 的值控制不同的从机。tx_buffer_process 这个函数就是前面通知使能中使用主机 cccd 写函数,这里同样可以作为写数据使用。



标签: #蓝牙# #NRF52840#

版权声明:
作者:lgy198612
链接:https://www.dianziwang.net/p/50d538f9dc727.html
来源:RF/无线
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以点击 “举报”


登录 后发表评论
0条评论
还没有人评论过~