码迷,mamicode.com
首页 > 其他好文 > 详细

nrf51822 --- 1拖8实验(1)

时间:2016-04-26 20:56:31      阅读:510      评论:0      收藏:0      [点我收藏+]

标签:

1.目的

    在SDK10.0\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay\pca10028\s130\arm4的基础上面添加一个控制串口服务,让其可以同时连接3个设备

2.分析  

   学习nrf51822主机和从机通信

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步骤.

    1.把ble_nus_c.c文件假如到工程。

 技术分享

添加对应的路径以及头文件

 技术分享


在main函数添加


/**@snippet [Handling events from the ble_nus_c module] */ 
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, const ble_nus_c_evt_t * p_ble_nus_evt)
{
    uint32_t err_code;
    switch (p_ble_nus_evt->evt_type)
    {
        case BLE_NUS_C_EVT_FOUND_NUS_TX_CHARACTERISTIC:
            APPL_LOG("The device has the device TX characteristic\r\n");
            break;
        
        case BLE_NUS_C_EVT_FOUND_NUS_RX_CHARACTERISTIC:
            err_code = ble_nus_c_rx_notif_enable(p_ble_nus_c);
            APP_ERROR_CHECK(err_code);
            APPL_LOG("The device has the device RX characteristic\r\n");
            break;       
        case BLE_NUS_C_EVT_NUS_RX_EVT:
            for (uint32_t i = 0; i < p_ble_nus_evt->data_len; i++)
            {
									 SEGGER_RTT_printf(0,"p_ble_nus_evt->p_data[%d]=%x\r\n", i,p_ble_nus_evt->p_data[i]);  //通过j-link的rtt发送接收到的数据
                //while(app_uart_put( p_ble_nus_evt->p_data[i]) != NRF_SUCCESS);
            }
            break;
        
        case BLE_NUS_C_EVT_DISCONNECTED:
            APPL_LOG("NUS device disconnected\r\n");
            scan_start();
            break;
    }
}


/**@brief Function for initializing the NUS Client.
 */
static void nus_c_init(ble_nus_c_t *ble_nus_c)
{
    uint32_t         err_code;
    ble_nus_c_init_t nus_c_init_t;
    
    nus_c_init_t.evt_handler = ble_nus_c_evt_handler;
    
    err_code = ble_nus_c_init(ble_nus_c, &nus_c_init_t);
    APP_ERROR_CHECK(err_code);
}

on_ble_central_evt()中函数改为如下

static void on_ble_central_evt(const ble_evt_t * const p_ble_evt)
{
    // The addresses of peers we attempted to connect to.
    static ble_gap_addr_t periph_addr_hrs;
    static ble_gap_addr_t periph_addr_rsc;
    static ble_gap_addr_t periph_addr_nus;//定义连接外部具有串口服务的蓝牙地址
    // For readability.
    const ble_gap_evt_t   * const p_gap_evt = &p_ble_evt->evt.gap_evt;
    
    switch (p_ble_evt->header.evt_id)
    {
        /** Upon connection, check which peripheral has connected (HR or RSC), initiate DB
         *  discovery, update LEDs status and resume scanning if necessary. */
        case BLE_GAP_EVT_CONNECTED:
        {
					  uint8_t i = 0;
            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));
               							 if(m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID)
								 {
                  m_conn_handle_nus_c = p_gap_evt->conn_handle;
									  m_ble_nus_c.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; //保存handle
							     err_code = ble_db_discovery_start(&m_ble_db_discovery_nus, p_gap_evt->conn_handle); //开始找服务
                   APP_ERROR_CHECK(err_code);
								 }else if(m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID)
								 {
                    m_conn_handle_hrs_c = p_gap_evt->conn_handle;
									  m_ble_hrs_c.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
							     err_code = ble_db_discovery_start(&m_ble_db_discovery_hrs, p_gap_evt->conn_handle);
                   APP_ERROR_CHECK(err_code);
								 } else if(m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID)
								 {                   m_conn_handle_rscs_c = p_gap_evt->conn_handle;
									  m_ble_rsc_c.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
							     err_code = ble_db_discovery_start(&m_ble_db_discovery_rsc, p_gap_evt->conn_handle);
                   APP_ERROR_CHECK(err_code);
								 }
					
								
							//	m_nus.conn_handle  =  p_gap_evt->conn_handle;
                NRF_LOG_PRINTF("Starting DB discovery for Nordic_UART\r\n");
           
            }           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
        /** Upon disconnection, reset the connection handle of the peer which disconnected, update
         * the LEDs status and start scanning again. */
        case BLE_GAP_EVT_DISCONNECTED: //蓝牙断开
        {
            uint8_t n_centrals ;
            uint8_t i = 0 ;
					
					    if (p_gap_evt->conn_handle == m_conn_handle_nus_c)//判断断开的是是不是串口服务哪个蓝牙
            {
                NRF_LOG_PRINTF(" central disconnected (reason: %d)\r\n",
                p_gap_evt->params.disconnected.reason);
                m_conn_handle_nus_c = BLE_CONN_HANDLE_INVALID;  //把handle初始化
						 
				  	
				 }  else					            if (p_gap_evt->conn_handle == m_conn_handle_hrs_c)//判断断开的外设是不是心率那个 
            {
                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; //初始化
            }
            else if(p_gap_evt->conn_handle == m_conn_handle_rscs_c)
            {
                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;
            }

            // 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

        case BLE_GAP_EVT_ADV_REPORT:       {
            uint32_t err_code;
            data_t   adv_data;
            data_t   type_data;
             bool        do_connect = false;
            // 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;
						err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
																										&adv_data,
																										&type_data);	//寻找名字字段				//	NRF_LOG_PRINTF("type_data.p_data[0]: %s)\r\n",type_data.p_data);//????
					//	NRF_LOG_PRINTF("lenght: %d\r\n",strlen("Nordic_UART")); //strlen("HRS")???????????
										
						if( memcmp(type_data.p_data,"Nordic_UART",strlen("Nordic_UART"))==0)//对比名字,是不是"Nordic_UART"
						{
							 memcpy(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t));//复制蓝牙mac
						  do_connect = true;	//赋值
      								
						}
						else 
					 {
 					   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++)
            {
               
                uint16_t    extracted_uuid;

                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. */
                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));
                }
                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);//通过地址mac连接蓝牙
                    if (err_code != NRF_SUCCESS)
                    {
                        APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code);
                    }
                }           
        } break; // BLE_GAP_ADV_REPORT

        case BLE_GAP_EVT_TIMEOUT:
        {
            // We have not specified a timeout for scanning, so only connection attemps can timeout.
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
            {
                APPL_LOG("[APPL]: Connection Request timed out.\r\n");
            }
        } break; // BLE_GAP_EVT_TIMEOUT
        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            // Accept parameters requested by peer.
            ret_code_t err_code;
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                        &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
        } break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST

        default:
            // No implementation needed.
            break;
    }
}

蓝牙协议栈事件回调

/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
 *
 * @details This function is called from the scheduler in the main loop after a BLE stack event has
 * been received.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 */
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
    uint16_t conn_handle;
    uint16_t role;

    /** The Connection state module has to be fed BLE events in order to function correctly
     * Remember to call ble_conn_state_on_ble_evt before calling any ble_conns_state_* functions. */
    ble_conn_state_on_ble_evt(p_ble_evt);

    pm_ble_evt_handler(p_ble_evt);
    // The connection handle should really be retrievable for any event type.
    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    role        = ble_conn_state_role(conn_handle);

    // Based on the role this device plays in the connection, dispatch to the right applications.
    if (role == BLE_GAP_ROLE_PERIPH) //判断角色。是不是外设事件
    {
        // Manages peripheral LEDs.
        on_ble_peripheral_evt(p_ble_evt);

        ble_advertising_on_ble_evt(p_ble_evt);
        ble_conn_params_on_ble_evt(p_ble_evt);

        // Dispatch to peripheral applications.
		  	//ble_nus_on_ble_evt (&m_nus, p_ble_evt);
        ble_hrs_on_ble_evt (&m_hrs, p_ble_evt);
        ble_rscs_on_ble_evt(&m_rscs, p_ble_evt);
    }
    else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))//判断是不是中心事件
    {       /** on_ble_central_evt will update the connection handles, so we want to execute it
         * after dispatching to the central applications upon disconnection. */
        if (p_ble_evt->header.evt_id != BLE_GAP_EVT_DISCONNECTED)
        {
            on_ble_central_evt(p_ble_evt);
        }

        if (conn_handle == m_conn_handle_hrs_c) 
        {       /** on_ble_central_evt will update the connection handles, so we want to execute it
         * after dispatching to the central applications upon disconnection. */
        if (p_ble_evt->header.evt_id != BLE_GAP_EVT_DISCONNECTED)
        {
            on_ble_central_evt(p_ble_evt);
        }

        if (conn_handle == m_conn_handle_hrs_c) //判断是不是hrs handle
        {           ble_hrs_c_on_ble_evt(&m_ble_hrs_c, p_ble_evt);
            ble_db_discovery_on_ble_evt(&m_ble_db_discovery_hrs, p_ble_evt); //产生对应的回调
        }
        else if (conn_handle == m_conn_handle_rscs_c) //判断是不是<span style="font-family: Arial;">   rscs handle                                                                                                                                              {</span><span style="font-family: Arial;">                                                                                                                                                                                                                                    ble_rscs_c_on_ble_evt(&m_ble_rsc_c, p_ble_evt);</span>
            ble_db_discovery_on_ble_evt(&m_ble_db_discovery_rsc, p_ble_evt);  //产生对应回调
       } else	 if (conn_handle == m_conn_handle_nus_c)//判断是不是串口 handle 
           {           ble_nus_c_on_ble_evt(&m_ble_nus_c, p_ble_evt);
            ble_db_discovery_on_ble_evt(&m_ble_db_discovery_nus, p_ble_evt);
          }
					 
	
				
        // If the peer disconnected, we update the connection handles last.
        if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED)
        {
            on_ble_central_evt(p_ble_evt);
        }
    }
}


主函数如下

int main(void)
{
    ret_code_t err_code;
    bool       erase_bonds;

    err_code = NRF_LOG_INIT();
    APP_ERROR_CHECK(err_code);
    SEGGER_RTT_Init();
    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();
    rscs_c_init();
		nus_c_init(&m_ble_nus_c);//这是添加的控制串口服务


		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);
    SEGGER_RTT_printf(0,"hello");
    for (;;)
    {
        // Wait for BLE events.
        power_manage();
    }
}


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

在main.c中添加如下代码

定时事件ID和时间

APP_TIMER_DEF(m_send_data_timer_id); 
#define SEND_DATA_TIMER_INTERVAL         APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER) /**< Heart rate measurement interval (ticks). */



void send_data_timeout_handler(void * p_context)
{
	 uint8_t data = 0x55;
	 if(m_nus.is_notification_enabled == true) //假如主机使能了从机通知
	 {
		  ble_nus_string_send(&m_nus,&data,1);//发送数据
	 }
}
/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module. This creates and starts application timers.
 */
static void timers_init(void)
{
	  uint32_t err_code;
   //定一个周期1s的事件,
    err_code = app_timer_create(&m_send_data_timer_id,
																	APP_TIMER_MODE_REPEATED, 
																   send_data_timeout_handler);

}


主函数如下

    /**@brief Application main function.
 */
int main(void)
{
    uint32_t err_code;
    bool erase_bonds;
    uint8_t  start_string[] = START_STRING;
 
    // Initialize.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
    uart_init();
	  timers_init();<span style="white-space:pre">	</span>//定义一个1s的事件
    buttons_leds_init(&erase_bonds);
    ble_stack_init();
    gap_params_init();
    services_init();
    advertising_init();
    conn_params_init();
        
    printf("%s",start_string);
	
    err_code = app_timer_start(m_send_data_timer_id, SEND_DATA_TIMER_INTERVAL, NULL);//开始这个事件
    APP_ERROR_CHECK(err_code);
	
    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
  
    // Enter main loop.
    for (;;)
    {
        power_manage();
    }
}


最后,把从机和主机程序分别下载到芯片里面。主机用j-link仿真并打开RTT功能(具体看:http://blog.csdn.net/a369000753/article/details/51192707 RTT的使用)

通过client工具,可以观察到数据如下,主机可以周期的接收到 0x55 的数据 ,正式从机发送的数据。。所以。。。。

 技术分享


ok。。。。。。。。。。。。。。。。。

总结:

   1.添加对应的控制服务

  2扫描要连接的蓝牙的特征

  3.连接蓝牙,并保存handle

  4.找服务和特征值。

  5.抛出发现完成事件

  6.断开初始化handle



nrf51822 --- 1拖8实验(1)

标签:

原文地址:http://blog.csdn.net/a369000753/article/details/51240138

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!