nrf52832作为从机,连接多主机的情况下,如何能感知出连接的主机的服务和特征呢?请给出具体的实现代码基于nrf52832软件库
时间: 2024-03-17 08:42:45 浏览: 174
在nrf52832的软件库中,可以使用SoftDevice API来实现BLE从机的连接和服务发现。具体实现代码如下:
首先,在初始化BLE从机时,需要开启SoftDevice和BLE从机模式:
```c
// 初始化SoftDevice
ret_code_t err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// 初始化BLE从机
ble_stack_init();
// 开启BLE从机模式
ble_gap_adv_start(&m_adv_params, APP_BLE_CONN_CFG_TAG);
```
然后,在连接建立后,可以在BLE事件处理函数中处理发现服务和特征的事件。在连接建立后,会触发BLE_GAP_EVT_CONNECTED事件,可以在该事件处理函数中启动服务发现过程:
```c
case BLE_GAP_EVT_CONNECTED:
{
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
// 开始服务发现
err_code = sd_ble_gattc_primary_services_discover(m_conn_handle, 0x0001, NULL);
APP_ERROR_CHECK(err_code);
break;
}
```
在服务发现过程中,会触发BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP事件和BLE_GATTC_EVT_CHAR_DISC_RSP事件。可以在这两个事件处理函数中获取服务和特征的UUID和句柄等信息:
```c
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
{
ble_gattc_evt_prim_srvc_disc_rsp_t *p_response = &p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp;
// 遍历所有发现的服务
for (uint32_t i = 0; i < p_response->count; i++)
{
ble_uuid_t uuid = p_response->services[i].uuid;
// 根据UUID判断服务类型
if (ble_uuid_cmp(&uuid, &m_svc_uuid) == 0)
{
// 保存服务句柄
m_svc_handle = p_response->services[i].handle_range.start_handle;
}
}
break;
}
case BLE_GATTC_EVT_CHAR_DISC_RSP:
{
ble_gattc_evt_char_disc_rsp_t *p_response = &p_ble_evt->evt.gattc_evt.params.char_disc_rsp;
// 遍历所有发现的特征
for (uint32_t i = 0; i < p_response->count; i++)
{
ble_uuid_t uuid = p_response->chars[i].uuid;
// 根据UUID判断特征类型
if (ble_uuid_cmp(&uuid, &m_char_uuid) == 0)
{
// 保存特征句柄
m_char_handle = p_response->chars[i].handle_value;
}
}
// 特征发现完成,可以进行读写操作等
break;
}
```
完整的实现代码可以参考以下示例代码:
```c
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "app_error.h"
#include "ble.h"
#include "ble_advdata.h"
#include "ble_conn_params.h"
#include "ble_nus.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#define DEVICE_NAME "My Device" /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms). */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms). */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
#define BLE_NUS_MAX_DATA_LEN (BLE_GATT_ATT_MTU_DEFAULT - 3) /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
// UUID of the service and characteristic to discover
static ble_uuid_t m_svc_uuid =
{
.uuid = BLE_UUID_NUS_SERVICE,
.type = NUS_SERVICE_UUID_TYPE
};
static ble_uuid_t m_char_uuid =
{
.uuid = BLE_UUID_NUS_TX_CHAR,
.type = NUS_SERVICE_UUID_TYPE
};
// Service and characteristic handles
static uint16_t m_svc_handle = BLE_GATT_HANDLE_INVALID;
static uint16_t m_char_handle = BLE_GATT_HANDLE_INVALID;
// Connection handle
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
// BLE stack initialization
static void ble_stack_init(void)
{
ret_code_t err_code;
// Initialize the SoftDevice handler module
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &NRF_BLE_GATT_DEFAULT_CFG);
APP_ERROR_CHECK(err_code);
// Enable BLE stack
err_code = nrf_sdh_ble_enable(&APP_BLE_OBSERVER_PRIO);
APP_ERROR_CHECK(err_code);
}
// Advertising initialization
static void advertising_init(void)
{
ret_code_t err_code;
// Declare and initialize a BLE advertising packet structure
ble_advdata_t advdata;
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;
// Declare and initialize a BLE advertising parameters structure
ble_gap_adv_params_t adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.primary_phy = BLE_GAP_PHY_1MBPS;
adv_params.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
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 = MSEC_TO_UNITS(1000, UNIT_0_625_MS);
// Start advertising
err_code = sd_ble_gap_adv_set_configure(&adv_handle, &advdata, &adv_params);
APP_ERROR_CHECK(err_code);
err_code = sd_ble_gap_adv_start(adv_handle, APP_BLE_CONN_CFG_TAG);
APP_ERROR_CHECK(err_code);
}
// BLE event handler
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
ret_code_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
{
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
// Start service discovery
err_code = sd_ble_gattc_primary_services_discover(m_conn_handle, 0x0001, NULL);
APP_ERROR_CHECK(err_code);
break;
}
case BLE_GAP_EVT_DISCONNECTED:
{
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;
}
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
{
ble_gattc_evt_prim_srvc_disc_rsp_t *p_response = &p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp;
// Traverse all discovered services
for (uint32_t i = 0; i < p_response->count; i++)
{
ble_uuid_t uuid = p_response->services[i].uuid;
// Determine the service type based on the UUID
if (ble_uuid_cmp(&uuid, &m_svc_uuid) == 0)
{
// Save the service handle
m_svc_handle = p_response->services[i].handle_range.start_handle;
}
}
break;
}
case BLE_GATTC_EVT_CHAR_DISC_RSP:
{
ble_gattc_evt_char_disc_rsp_t *p_response = &p_ble_evt->evt.gattc_evt.params.char_disc_rsp;
// Traverse all discovered characteristics
for (uint32_t i = 0; i < p_response->count; i++)
{
ble_uuid_t uuid = p_response->chars[i].uuid;
// Determine the characteristic type based on the UUID
if (ble_uuid_cmp(&uuid, &m_char_uuid) == 0)
{
// Save the characteristic handle
m_char_handle = p_response->chars[i].handle_value;
}
}
// Characteristic discovery completed, can perform read/write operations, etc.
break;
}
default:
// No implementation needed.
break;
}
}
// BLE stack initialization
static void ble_init(void)
{
ret_code_t err_code;
// Initialize BLE stack
ble_stack_init();
// Initialize GATT module
err_code = nrf_ble_gatt_init(&m_gatt, NULL);
APP_ERROR_CHECK(err_code);
// Initialize QWR module
err_code = nrf_ble_qwr_init(&m_qwr, &m_qwr_mem);
APP_ERROR_CHECK(err_code);
// Register BLE event handler
err_code = nrf_ble_gatt_cbs_register(&m_gatt, ble_evt_handler, NULL);
APP_ERROR_CHECK(err_code);
// Set the MTU size
err_code = sd_ble_gattc_exchange_mtu_request(m_conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
APP_ERROR_CHECK(err_code);
// Initialize advertising
advertising_init();
}
int main(void)
{
// Initialize BLE
ble_init();
while (true)
{
// Do nothing
}
}
```
阅读全文