nrf51822---主从一体通信(3)

来源:互联网 发布:底层数据读取错误率 编辑:程序博客网 时间:2024/06/03 00:32

.目的

   学习nrf51822主机和从机通信

2.分析

    nrf51822---主从通信(1)和nrf51822---主从通信(2)都是在已知服务的基础上面来找的。但是在实际中并不知道对方的属性,可能只告诉你要连接蓝牙的名字。那怎么办呢???

3.平台:

协议栈版本:SDK10.0.0

编译软件:keil 5.12

硬件平台:nrf51822最小系统

例子:SDK 10.0.0\examples\ble_peripheral\ble_app_uart\pca10028\s110\arm4 从机例子

          SDK10.0\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay\pca10028\s130\arm4 做主机

4步骤.

  首先来大概分析下代码。

    首先在主函数里.2个从机,控制服务初始化的过程,然后扫描开始,广播开始,即主从一体

  

int main(void){    ret_code_t err_code;    bool       erase_bonds;    err_code = NRF_LOG_INIT();    APP_ERROR_CHECK(err_code);    NRF_LOG_PRINTF("Relay Example\r\n");    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);    buttons_leds_init(&erase_bonds);    if (erase_bonds == true)    {        NRF_LOG("Bonds erased!\r\n");    }    ble_stack_init();    peer_manager_init(erase_bonds);    db_discovery_init();    hrs_c_init();  //HES初始化    rscs_c_init(); //rscs初始化    gap_params_init();    conn_params_init();    services_init();    advertising_init();    /** Start scanning for peripherals and initiate connection to devices which     *  advertise Heart Rate or Running speed and cadence UUIDs. */    scan_start(); //扫描开始    // Turn on the LED to signal scanning.    LEDS_ON(CENTRAL_SCANNING_LED);    // Start advertising.    err_code = ble_advertising_start(BLE_ADV_MODE_FAST); //广播初始化    APP_ERROR_CHECK(err_code);    for (;;)    {        // Wait for BLE events.        power_manage();    }}


接下来看扫描到了广播,产生BLE_GAP_EVT_ADV_REPORT事件代码:


 case BLE_GAP_EVT_ADV_REPORT:        {            uint32_t err_code;            data_t   adv_data;            data_t   type_data;            // For readibility.  找到扫描的地址            const ble_gap_addr_t  * const peer_addr = &p_gap_evt->params.adv_report.peer_addr;            // Initialize advertisement report for parsing.            adv_data.p_data     = (uint8_t *)p_gap_evt->params.adv_report.data;  //扫描广播的数据地址            adv_data.data_len   = p_gap_evt->params.adv_report.dlen;  //扫描广播的长度            //找标识符为BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE的数据地址和长度            err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,                                        &adv_data,                                        &type_data);      if (err_code != NRF_SUCCESS)            {                // Look for the services in 'complete' if it was not found in 'more available'.                err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,                                            &adv_data,                                            &type_data);                if (err_code != NRF_SUCCESS)                {                    // If we can't parse the data, then exit.                    break;                }            }            // Verify if any UUID match the Heart rate or Running speed and cadence services.            for (uint32_t u_index = 0; u_index < (type_data.data_len / UUID16_SIZE); u_index++)            {                bool        do_connect = false;                uint16_t    extracted_uuid;                  //复制出UUID到extracted                UUID16_EXTRACT(&extracted_uuid, &type_data.p_data[u_index * UUID16_SIZE]);                /** We do not want to connect to two peripherals offering the same service, so when                 *  a UUID is matched, we check that we are not already connected to a peer which                 *  offers the same service. We then save the peer address, so that upon connection                 *  we can tell which peer has connected and update its respective connection                 *  handle. */ //判断UUID是不是心率的UUID并且看是否已经连上了                if ((extracted_uuid      == BLE_UUID_HEART_RATE_SERVICE) &&                    (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID))                {               do_connect = true;                    memcpy(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)); //复制扫描的蓝牙地址到periph_addr_hrs                }    //或者UUID是不是RSCS的UUID并且没有连上                else if ((extracted_uuid       == BLE_UUID_RUNNING_SPEED_AND_CADENCE) &&                         (m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID))                {                    do_connect = true;                    memcpy(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)); //复制蓝牙地址                }                if (do_connect)                {                    // Initiate connection.   //连接这地址的设备                    err_code = sd_ble_gap_connect(peer_addr, &m_scan_param, &m_connection_param);                    if (err_code != NRF_SUCCESS)                    {                        APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code);                    }                }            }        } break; // BLE_GAP_ADV_REPORT

 如果连上了设备则产生BLE_GAP_EVT_CONNECTED事件

  

   case BLE_GAP_EVT_CONNECTED:        {            uint32_t err_code;            // For readability.            const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.connected.peer_addr;  //找到蓝牙的地址            /** Check which peer has connected, save the connection handle and initiate DB discovery.             *  DB discovery will invoke a callback (hrs_c_evt_handler and rscs_c_evt_handler)             *  upon completion, which is used to enable notifications from the peer. */                                                                           if(memcmp(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)) == 0)  //连接上的蓝牙地址和和被连接的蓝牙地址对比 一直则正确            {                NRF_LOG_PRINTF("HRS central connected\r\n");                // Reset the peer address we had saved.                memset(&periph_addr_hrs, 0, sizeof(ble_gap_addr_t));                m_conn_handle_hrs_c = p_gap_evt->conn_handle;  //保存连接的handle  这个很总有可以用来区别哪个设备                NRF_LOG_PRINTF("Starting DB discovery for HRS\r\n");                err_code = ble_db_discovery_start(&m_ble_db_discovery_hrs, p_gap_evt->conn_handle);  //开始发现服务                APP_ERROR_CHECK(err_code);            }            else if(memcmp(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)) == 0)  <span style="font-family: Arial, Helvetica, sans-serif;">//连接上的蓝牙地址和和被连接的蓝牙地址对比 一直则正确</span>            {                NRF_LOG_PRINTF("RSC central connected\r\n");                // Reset the peer address we had saved.                memset(&periph_addr_rsc, 0, sizeof(ble_gap_addr_t));                 m_conn_handle_rscs_c = p_gap_evt->conn_handle;//保存连接的handle                NRF_LOG_PRINTF("Starting DB discovery for RSCS\r\n");                err_code = ble_db_discovery_start(&m_ble_db_discovery_rsc, p_gap_evt->conn_handle);  //开始扫描服务设备                APP_ERROR_CHECK(err_code);            }            /** Update LEDs status, and check if we should be looking for more             *  peripherals to connect to. */            LEDS_ON(CENTRAL_CONNECTED_LED);            if (ble_conn_state_n_centrals() == MAX_CONNECTED_CENTRALS)//判断连接的设备是否为设定的设备值            {                LEDS_OFF(CENTRAL_SCANNING_LED);//            }            else         {                // Resume scanning.                LEDS_ON(CENTRAL_SCANNING_LED);                scan_start();  //继续扫描            }        } break; // BLE_GAP_EVT_CONNECTED


断开某设备。会产生BLE_GAP_EVT_DISCONNECTED事件,

  case BLE_GAP_EVT_DISCONNECTED:        {            uint8_t n_centrals;            if (p_gap_evt->conn_handle == m_conn_handle_hrs_c) //判断断开的设备是哪个设备,是否为HRS设备。找出对应的handle            {                NRF_LOG_PRINTF("HRS central disconnected (reason: %d)\r\n",                       p_gap_evt->params.disconnected.reason);                m_conn_handle_hrs_c = BLE_CONN_HANDLE_INVALID;  //handle初始化            }            else if(p_gap_evt->conn_handle == m_conn_handle_rscs_c) //判断断开的设备是不是RSCS设备            {                NRF_LOG_PRINTF("RSC central disconnected (reason: %d)\r\n",                       p_gap_evt->params.disconnected.reason);                m_conn_handle_rscs_c = BLE_CONN_HANDLE_INVALID; //handle初始化            }            // Start scanning            scan_start(); //这里会不会冲突。            // Update LEDs status.            LEDS_ON(CENTRAL_SCANNING_LED);            n_centrals = ble_conn_state_n_centrals();            if (n_centrals == 0)            {                LEDS_OFF(CENTRAL_CONNECTED_LED);            }        } break; // BLE_GAP_EVT_DISCONNECTED

以上代码发现,如果连上了2个设备这个时候,不再scan_start(),在使用中断开了一个设备是否需要从新scan_start()再次连接一个呢?或者又如,值连接了一个设备,并且主机也还在扫描,并且这个连上的设备也断开了,假如调用了scan_start();会怎么样?实验证明无影响。。



0 0