nrf51822 --- 主从通信(2)

1.目的

   学习nrf51822主机和从机通信

2.分析

    2个设备,一个做主机一个做从机,相互通信   

3.平台:

协议栈版本:SDK10.0.0

编译软件:keil 5.12

硬件平台:nrf51822最小系统

例子: SDK10.0\examples\ble_peripheral\ble_app_hrs\pca10028\s110\arm4 从机例子

            SDK10.0\examples\ble_central\ble_app_hrs_c\pca10028\s120 做主机

4.代码分析

  上一篇文章是串口(nrf51822 --- 主从通信)主机的大概分析,上面只有一个服务以及一个服务下面有2个特征值。假如事件应用中有多个服务怎么办呢?接下来来分析,如何发现多个特征值的。以心率例子为例 SDK10.0\examples\ble_peripheral\ble_app_hrs\pca10028\s110\arm4

 主函数了里面,红色方框,是初始化心率和电池的控制初始化。

 hrs_c_init();主要完成收集回调函数,以及心率UUID类型初始化和以及发现回调函数的初始化过程

 bas_c_init();主要完成收集回调函数,以及电池UUID类型初始化和以及发现回调函数的初始化过程

注意:这里都是在已知,从机已知特定服务,以及特征值的情况下的连接情况

  nrf51822 --- 主从通信(2)_第1张图片

  

这里注意m_num_of_handlers_reg这里是定义主服务控制的个数,DB_DISCOVERY_MAX_USERS红定义限制定义服务数

static uint32_t registered_handler_set(const ble_uuid_t * const       p_srv_uuid,
                                       ble_db_discovery_evt_handler_t p_evt_handler)
{
    if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS)
    {
        m_registered_handlers[m_num_of_handlers_reg].srv_uuid    = *p_srv_uuid;
        m_registered_handlers[m_num_of_handlers_reg].evt_handler = p_evt_handler;

        m_num_of_handlers_reg++;

        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_NO_MEM;
    }
}


 扫描的国产和nrf51822 --- 主从通信)差不多,唯一不一样的是心率代码有绑定过程,开始找服务的函数在

 nrf51822 --- 主从通信(2)_第2张图片

发现服务后会产生case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:事件--->on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); -->err_code = characteristics_discover(p_db_discovery);发现特征值-->case BLE_GATTC_EVT_CHAR_DISC_RSP:-->on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));-->判断是否特征值已经全部发现或者特征值超过了预定义的个数

---> err_code = characteristics_discover(p_db_discovery);(开始扫描描述符)-->case BLE_GATTC_EVT_DESC_DISC_RSP:事件--> on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));(继续发现描述符,并且判断特征值已经全部发现或者特征值超过了预定义的个数)-->判断是否发现完毕①

if (raise_discov_complete)
    {
        DB_LOG("[DB]: Discovery of service with UUID 0x%x completed with success for Connection"
               "handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid,
               p_db_discovery->conn_handle);


        discovery_complete_evt_trigger(p_db_discovery, true);
      
        on_srv_disc_completion(p_db_discovery);
    }

这个发现完毕会产生对应的控制回调函数  discovery_complete_evt_trigger(p_db_discovery, true);,然后执行 on_srv_disc_completion(p_db_discovery);

这里面m_num_of_handlers_reg是刚才是注册时候的定义主服务控制的个数registered_handler_set();函数,一开始定义了心率和电池电量的服务控制2个,所以当第一次扫描完成的时候,if(true) 所以,sd_ble_gattc_primary_services_discover()函数继续 找服务。找完之后又会到这里,但是这里if(false)表示完成,发现服务完毕,如果没有完全发现完服务需要把把一些参数初始化。

 注意:但是假如在不知道服务个数的情况怎么办呢?是不是m_num_of_handlers_reg要变大?

           以及一次最多能发现多少个特征值呢?


static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery)
{
    p_db_discovery->discoveries_count++;

    // Check if more services need to be discovered.
    if (p_db_discovery->discoveries_count < m_num_of_handlers_reg)
    {   //重新发现服务以及特征值,需要把一些参数初始化,
        // Reset the current characteristic index since a new service discovery is about to start.
        p_db_discovery->curr_char_ind = 0;

        // Initiate discovery of the next service.
        p_db_discovery->curr_srv_ind++; //下一个服务的位置。也就是地址累加

        ble_gatt_db_srv_t * p_srv_being_discovered;

        p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);

        p_srv_being_discovered->srv_uuid =
            m_registered_handlers[p_db_discovery->curr_srv_ind].srv_uuid;
        // Reset the characteristic count in the current service to zero since a new service
        // discovery is about to start.
        p_srv_being_discovered->char_count = 0; //特征值个数要清掉,重新发现

        DB_LOG("[DB]: Starting discovery of service with UUID 0x%x for Connection handle %d\r\n",
               p_srv_being_discovered->srv_uuid.uuid, p_db_discovery->conn_handle);

        uint32_t err_code;

        err_code = sd_ble_gattc_primary_services_discover
                   (
                   p_db_discovery->conn_handle,
                   SRV_DISC_START_HANDLE,
                   &(p_srv_being_discovered->srv_uuid)
                   );       if (err_code != NRF_SUCCESS)
        {
            p_db_discovery->discovery_in_progress = false;
            //SEGGER_RTT_printf(0,"error\r\n");
            // Error with discovering the service.
            // Indicate the error to the registered user application.
            discovery_error_evt_trigger(p_db_discovery, err_code);

            return;
        }
    }
    else
    {
        // No more service discovery is needed.
        p_db_discovery->discovery_in_progress = false;
    }
}


看下面回调函数,扫描完成了,可以得到服务特征值的个数,然后找到和BLE_UUID_HEART_RATE_MEASUREMENT_CHAR相当的位子,把CCCD和handle保存下来,因为值为BLE_UUID_HEART_RATE_MEASUREMENT_CHAR特征值具有notify的属性,需要主机使能notify,所以需要知道CCCD和handle(handle可以理解为扫描发现服务的地址,然后主机可以通过地址使能通道)

 但是在实际应用中假如未知从机属性怎么办?可以通过UUID的属性值来保存Handle,如下:

      if (p_evt->params.discovered_db.charateristics[i].characteristic.char_props.notify == 1)

     {

   //保存cccd和handle

      // Found Heart Rate characteristic. Store CCCD handle and break.
                mp_ble_hrs_c->hrm_cccd_handle =
                p_evt->params.discovered_db.charateristics[i].cccd_handle;
                mp_ble_hrs_c->hrm_handle      =
                  p_evt->params.discovered_db.charateristics[i].characteristic.handle_value;

     }

  假如,要知道wirte的属性的handle也可以通过上面的方法。。

static void db_discover_evt_handler(ble_db_discovery_evt_t * p_evt)
{
    // Check if the Heart Rate Service was discovered.
    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
        p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_HEART_RATE_SERVICE &&
        p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE)
    {
        mp_ble_hrs_c->conn_handle = p_evt->conn_handle;

        // Find the CCCD Handle of the Heart Rate Measurement characteristic.
        uint32_t i;
         //
        for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
        {   //扫描到的特征值和定义的特征值相等的位子,然后把CCCD和handle保存下来,
            if (p_evt->params.discovered_db.charateristics[i].characteristic.uuid.uuid ==
                BLE_UUID_HEART_RATE_MEASUREMENT_CHAR)
            {               // Found Heart Rate characteristic. Store CCCD handle and break.
                mp_ble_hrs_c->hrm_cccd_handle =
                    p_evt->params.discovered_db.charateristics[i].cccd_handle;
                mp_ble_hrs_c->hrm_handle      =
                    p_evt->params.discovered_db.charateristics[i].characteristic.handle_value;
                break;
            }
        }

        LOG("[HRS_C]: Heart Rate Service discovered at peer.\r\n");

        ble_hrs_c_evt_t evt;

        evt.evt_type = BLE_HRS_C_EVT_DISCOVERY_COMPLETE;

        mp_ble_hrs_c->evt_handler(mp_ble_hrs_c, &evt);
    }
}


 
 

你可能感兴趣的:(nrf51822 --- 主从通信(2))