欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Nordic nRF5 SDK 学习笔记之二, 蓝牙主机与从机建立联结及服务发现过程

程序员文章站 2024-03-21 15:36:46
...

基于 NORDIC softDevice 蓝牙协议栈 S132, nRF5 SDK Ver 15.0.0

蓝牙角色: 机,ble_central

文章内容: 蓝牙主机与从机建立联结及服务发现过程

程序样例: nRF5_SDK_15.0.0\examples\ble_central\ble_app_uart_c


关于NORDIC softDevice 蓝牙协议栈主机的蓝牙初始化,请参见博客文章: NORDIC softDevice 蓝牙协议栈初始化程序分析(蓝牙主机,ble_central)


蓝牙主机与从机的联结及服务发现过程图

Nordic nRF5 SDK 学习笔记之二, 蓝牙主机与从机建立联结及服务发现过程

 


程序调用流程

蓝牙主机扫描启动, scan_start()

1. 发现广播从机,并触发广播报告事件;

回调函数 ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) 处理 BLE_GAP_EVT_ADV_REPORT 事件; 

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ...
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_ADV_REPORT:
            on_adv_report(&p_gap_evt->params.adv_report);
            break; // BLE_GAP_EVT_ADV_REPORT
            ...
}

2. 判断广播报告中 UUID 是否为需要的 UUID ?

    处理函数 on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report); 

    判断函数 ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &m_nus_uuid);

static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report)
{
    ret_code_t err_code;

    if (ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &m_nus_uuid))
    { 
        ...
    }
}

3. 联结蓝牙从机,并触发联结事件 (注: 蓝牙实际是通过 MAC 地址进行联结的

    BLE 联结函数 sd_ble_gap_connect(&p_adv_report->peer_addr,

           &m_scan_params,&m_connection_param,APP_BLE_CONN_CFG_TAG);

static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report)
{
    ret_code_t err_code;

    if (ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &m_nus_uuid))
    {
        err_code = sd_ble_gap_connect(&p_adv_report->peer_addr,
                                      &m_scan_params,
                                      &m_connection_param,
                                      APP_BLE_CONN_CFG_TAG);
        ...
    }
}

4. 蓝牙联结成功后,启动蓝牙服务数据发现 ble_db_discovery_start(),

   并**服务发现回调函数 ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt,void            * p_context);

    蓝牙联结事件处理函数 ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context);

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t            err_code;
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        ...
        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("Connected to target");
            err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
            APP_ERROR_CHECK(err_code);

            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);

            // start discovery of services. The NUS Client waits for a discovery result
            err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
            APP_ERROR_CHECK(err_code);
            break;
        ...
    }
}

5. 蓝牙发现主服务事件处理, 处理函数: ble_db_discovery_on_ble_evt();

    处理事件 BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP;

void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt,
                                 void            * p_context)
{
    VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    VERIFY_PARAM_NOT_NULL_VOID(p_context);
    VERIFY_MODULE_INITIALIZED_VOID();

    ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
            on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
            break;
        ...
    }
}

6. 蓝牙发现服务特征值事件处理, 处理函数: ble_db_discovery_on_ble_evt();

void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt,
                                 void            * p_context)
{
    VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    VERIFY_PARAM_NOT_NULL_VOID(p_context);
    VERIFY_MODULE_INITIALIZED_VOID();

    ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context;

    switch (p_ble_evt->header.evt_id)
    {
        ...
        case BLE_GATTC_EVT_CHAR_DISC_RSP:
            on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
            break;
        ...
    }
}

7. 蓝牙发现描述符事件处理, 处理函数: ble_db_discovery_on_ble_evt();

void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt,
                                 void            * p_context)
{
    VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    VERIFY_PARAM_NOT_NULL_VOID(p_context);
    VERIFY_MODULE_INITIALIZED_VOID();

    ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context;

    switch (p_ble_evt->header.evt_id)
    {
        ...
        case BLE_GATTC_EVT_DESC_DISC_RSP:
            on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
            break;

        ...
    }
}