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

基于 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)


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


程序调用流程

蓝牙主机扫描启动, 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;

        ...
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42396877/article/details/81284190