低功耗蓝牙4.0BLE编程- nrf51822开发板开发(2)

首先看的示例是心率计一个示例程序:<KEIL path> \ARM\Device\Nordic\nrf51822\Board\pca10001\s110\ble_app_hrs\arm。

    打开工程前需要下载蓝牙协议栈S110 nRF51822 SoftDevice(s110_nrf51822_6.0.0_softdevice.hex)到板子中,这个手册上有说明。

    首先看的是main.c中的main函数:

  1. /***************************************************************************** 
  2. * Main Function 
  3. *****************************************************************************/  
  4.   
  5. /**@brief Function for the application main entry. 
  6.  */  
  7. int main(void)  
  8. {  
  9.     uint32_t err_code;  
  10.   
  11.     timers_init();  
  12.     gpiote_init();  
  13.     buttons_init();  
  14.     ble_stack_init();  
  15.     bond_manager_init();  
  16.   
  17.     // Initialize Bluetooth Stack parameters  
  18.     gap_params_init();  
  19.     advertising_init();  
  20.     services_init();  
  21.     conn_params_init();  
  22.     sec_params_init();  
  23.   
  24.     // Start advertising   
  25.     advertising_start();  
  26.   
  27.     // Enter main loop   
  28.     for (;;)  
  29.     {  
  30.         // Switch to a low power state until an event is available for the application  
  31.         err_code = sd_app_evt_wait();  
  32.         APP_ERROR_CHECK(err_code);  
  33.     }  
  34. }  
/*****************************************************************************
* Main Function
*****************************************************************************/

/**@brief Function for the application main entry.
 */
int main(void)
{
    uint32_t err_code;

    timers_init();
    gpiote_init();
    buttons_init();
    ble_stack_init();
    bond_manager_init();

    // Initialize Bluetooth Stack parameters
    gap_params_init();
    advertising_init();
    services_init();
    conn_params_init();
    sec_params_init();

    // Start advertising
    advertising_start();

    // Enter main loop
    for (;;)
    {
        // Switch to a low power state until an event is available for the application
        err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
}

它很简洁:初始化->start->loop。

(1)Timer初始化

  1. /**@brief Function for the Timer initialization. 
  2.  * 
  3. * @details Initializes the timer module. This creates and starts application timers. 
  4. */  
  5. static void timers_init(void)  
  6. {  
  7.     uint32_t err_code;  
  8.   
  9.     // Initialize timer module  
  10.     APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);  
  11.   
  12.     // Create timers   
  13.     err_code = app_timer_create(&m_battery_timer_id,  
  14.                                 APP_TIMER_MODE_REPEATED,  
  15.                                 battery_level_meas_timeout_handler);  
  16.     APP_ERROR_CHECK(err_code);  
  17.   
  18.     err_code = app_timer_create(&m_heart_rate_timer_id,  
  19.                                 APP_TIMER_MODE_REPEATED,  
  20.                                 heart_rate_meas_timeout_handler);  
  21.     APP_ERROR_CHECK(err_code);  
  22. }  
/**@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;

    // Initialize timer module
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);

    // Create timers
    err_code = app_timer_create(&m_battery_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                battery_level_meas_timeout_handler);
    APP_ERROR_CHECK(err_code);

    err_code = app_timer_create(&m_heart_rate_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                heart_rate_meas_timeout_handler);
    APP_ERROR_CHECK(err_code);
}

使用app_timer_create创建了两个时钟,处理函数分别是battery_level_meas_timeout_handler和heart_rate_meas_timeout_handler。

  1. /**@brief Function for handling the Battery measurement timer timeout. 
  2.  * 
  3.  * @details This function will be called each time the battery level measurement timer expires. 
  4.  *          This function will start the ADC. 
  5.  * 
  6.  * @param[in]   p_context   Pointer used for passing some arbitrary information (context) from the 
  7.  *                          app_start_timer() call to the timeout handler. 
  8.  */  
  9. static void battery_level_meas_timeout_handler(void * p_context)  
  10. {  
  11.     UNUSED_PARAMETER(p_context);  
  12.     battery_start();  
  13. }  
  14.   
  15.   
  16. /**@brief Function for handling the Heart rate measurement timer timeout. 
  17.  * 
  18.  * @details This function will be called each time the heart rate measurement timer expires. 
  19.  *          It will exclude RR Interval data from every third measurement. 
  20.  * 
  21.  * @param[in]   p_context   Pointer used for passing some arbitrary information (context) from the 
  22.  *                          app_start_timer() call to the timeout handler. 
  23.  */  
  24. static void heart_rate_meas_timeout_handler(void * p_context)  
  25. {  
  26.     uint32_t err_code;  
  27.   
  28.     UNUSED_PARAMETER(p_context);  
  29.   
  30.     err_code = ble_hrs_heart_rate_measurement_send(&m_hrs, m_cur_heart_rate);  
  31.   
  32.     if (  
  33.         (err_code != NRF_SUCCESS)  
  34.         &&  
  35.         (err_code != NRF_ERROR_INVALID_STATE)  
  36.         &&  
  37.         (err_code != BLE_ERROR_NO_TX_BUFFERS)  
  38.         &&  
  39.         (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)  
  40.     )  
  41.     {  
  42.         APP_ERROR_HANDLER(err_code);  
  43.     }  
  44. }  
/**@brief Function for handling the Battery measurement timer timeout.
 *
 * @details This function will be called each time the battery level measurement timer expires.
 *          This function will start the ADC.
 *
 * @param[in]   p_context   Pointer used for passing some arbitrary information (context) from the
 *                          app_start_timer() call to the timeout handler.
 */
static void battery_level_meas_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    battery_start();
}


/**@brief Function for handling the Heart rate measurement timer timeout.
 *
 * @details This function will be called each time the heart rate measurement timer expires.
 *          It will exclude RR Interval data from every third measurement.
 *
 * @param[in]   p_context   Pointer used for passing some arbitrary information (context) from the
 *                          app_start_timer() call to the timeout handler.
 */
static void heart_rate_meas_timeout_handler(void * p_context)
{
    uint32_t err_code;

    UNUSED_PARAMETER(p_context);

    err_code = ble_hrs_heart_rate_measurement_send(&m_hrs, m_cur_heart_rate);

    if (
        (err_code != NRF_SUCCESS)
        &&
        (err_code != NRF_ERROR_INVALID_STATE)
        &&
        (err_code != BLE_ERROR_NO_TX_BUFFERS)
        &&
        (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
    )
    {
        APP_ERROR_HANDLER(err_code);
    }
}

时钟创建后并不会自动运行,当调用application_timers_start后时钟开始运行:

  1. /**@brief Function for starting the application timers. 
  2.  */  
  3. static void application_timers_start(void)  
  4. {  
  5.     uint32_t err_code;  
  6.   
  7.     // Start application timers  
  8.     err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);  
  9.     APP_ERROR_CHECK(err_code);  
  10.   
  11.     err_code = app_timer_start(m_heart_rate_timer_id, HEART_RATE_MEAS_INTERVAL, NULL);  
  12.     APP_ERROR_CHECK(err_code);  
  13. }  
/**@brief Function for starting the application timers.
 */
static void application_timers_start(void)
{
    uint32_t err_code;

    // Start application timers
    err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = app_timer_start(m_heart_rate_timer_id, HEART_RATE_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);
}

services_init()初始化程序中的三个服务:ble_dis.c, ble_bas.c, ble_hrs.c。

  1. /**@brief Function for initializing the services that will be used by the application. 
  2.  * 
  3.  * @details Initialize the Heart Rate, Battery and Device Information services. 
  4.  */  
  5. static void services_init(void)  
  6. {  
  7.     uint32_t       err_code;  
  8.     ble_hrs_init_t hrs_init;  
  9.     ble_bas_init_t bas_init;  
  10.     ble_dis_init_t dis_init;  
  11.     uint8_t        body_sensor_location;  
  12.   
  13.     // Initialize Heart Rate Service  
  14.     body_sensor_location = BLE_HRS_BODY_SENSOR_LOCATION_FINGER;  
  15.   
  16.     memset(&hrs_init, 0, sizeof(hrs_init));  
  17.       
  18.     hrs_init.is_sensor_contact_supported = false;  
  19.     hrs_init.p_body_sensor_location      = &body_sensor_location;  
  20.   
  21.     // Here the sec level for the Heart Rate Service can be changed/increased.  
  22.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.cccd_write_perm);  
  23.     BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.read_perm);  
  24.     BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.write_perm);  
  25.   
  26.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_bsl_attr_md.read_perm);  
  27.     BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_bsl_attr_md.write_perm);  
  28.   
  29.     err_code = ble_hrs_init(&m_hrs, &hrs_init);  
  30.     APP_ERROR_CHECK(err_code);  
  31.   
  32.     // Initialize Battery Service   
  33.     memset(&bas_init, 0, sizeof(bas_init));  
  34.   
  35.     // Here the sec level for the Battery Service can be changed/increased.  
  36.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);  
  37.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);  
  38.     BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);  
  39.   
  40.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);  
  41.   
  42.     bas_init.evt_handler          = NULL;  
  43.     bas_init.support_notification = true;  
  44.     bas_init.p_report_ref         = NULL;  
  45.     bas_init.initial_batt_level   = 100;  
  46.   
  47.     err_code = ble_bas_init(&bas, &bas_init);  
  48.     APP_ERROR_CHECK(err_code);  
  49.   
  50.     // Initialize Device Information Service  
  51.     memset(&dis_init, 0, sizeof(dis_init));  
  52.   
  53.     ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);  
  54.   
  55.     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);  
  56.     BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);  
  57.   
  58.     err_code = ble_dis_init(&dis_init);  
  59.     APP_ERROR_CHECK(err_code);  
  60. }  
/**@brief Function for initializing the services that will be used by the application.
 *
 * @details Initialize the Heart Rate, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t       err_code;
    ble_hrs_init_t hrs_init;
    ble_bas_init_t bas_init;
    ble_dis_init_t dis_init;
    uint8_t        body_sensor_location;

    // Initialize Heart Rate Service
    body_sensor_location = BLE_HRS_BODY_SENSOR_LOCATION_FINGER;

    memset(&hrs_init, 0, sizeof(hrs_init));
    
    hrs_init.is_sensor_contact_supported = false;
    hrs_init.p_body_sensor_location      = &body_sensor_location;

    // Here the sec level for the Heart Rate Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_bsl_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_bsl_attr_md.write_perm);

    err_code = ble_hrs_init(&m_hrs, &hrs_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Battery Service
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}

static ble_hrs_t的结构定义:

  1. /**@brief Heart Rate Service structure. This contains various status information for the service. */  
  2. typedef struct ble_hrs_s  
  3. {  
  4.     ble_hrs_evt_handler_t        evt_handler;                                          /**< Event handler to be called for handling events in the Heart Rate Service. */  
  5.     bool                         is_expended_energy_supported;                         /**< TRUE if Expended Energy measurement is supported. */  
  6.     bool                         is_sensor_contact_supported;                          /**< TRUE if sensor contact detection is supported. */  
  7.     uint16_t                     service_handle;                                       /**< Handle of Heart Rate Service (as provided by the BLE stack). */  
  8.     ble_gatts_char_handles_t     hrm_handles;                                          /**< Handles related to the Heart Rate Measurement characteristic. */  
  9.     ble_gatts_char_handles_t     bsl_handles;                                          /**< Handles related to the Body Sensor Location characteristic. */  
  10.     ble_gatts_char_handles_t     hrcp_handles;                                         /**< Handles related to the Heart Rate Control Point characteristic. */  
  11.     uint16_t                     conn_handle;                                          /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */  
  12.     bool                         is_sensor_contact_detected;                           /**< TRUE if sensor contact has been detected. */  
  13.     uint16_t                     rr_interval[BLE_HRS_MAX_BUFFERED_RR_INTERVALS];       /**< Set of RR Interval measurements since the last Heart Rate Measurement transmission. */  
  14.     uint16_t                     rr_interval_count;                                    /**< Number of RR Interval measurements since the last Heart Rate Measurement transmission. */  
  15. } ble_hrs_t;  
/**@brief Heart Rate Service structure. This contains various status information for the service. */
typedef struct ble_hrs_s
{
    ble_hrs_evt_handler_t        evt_handler;                                          /**< Event handler to be called for handling events in the Heart Rate Service. */
    bool                         is_expended_energy_supported;                         /**< TRUE if Expended Energy measurement is supported. */
    bool                         is_sensor_contact_supported;                          /**< TRUE if sensor contact detection is supported. */
    uint16_t                     service_handle;                                       /**< Handle of Heart Rate Service (as provided by the BLE stack). */
    ble_gatts_char_handles_t     hrm_handles;                                          /**< Handles related to the Heart Rate Measurement characteristic. */
    ble_gatts_char_handles_t     bsl_handles;                                          /**< Handles related to the Body Sensor Location characteristic. */
    ble_gatts_char_handles_t     hrcp_handles;                                         /**< Handles related to the Heart Rate Control Point characteristic. */
    uint16_t                     conn_handle;                                          /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */
    bool                         is_sensor_contact_detected;                           /**< TRUE if sensor contact has been detected. */
    uint16_t                     rr_interval[BLE_HRS_MAX_BUFFERED_RR_INTERVALS];       /**< Set of RR Interval measurements since the last Heart Rate Measurement transmission. */
    uint16_t                     rr_interval_count;                                    /**< Number of RR Interval measurements since the last Heart Rate Measurement transmission. */
} ble_hrs_t;

ble_hrs.h/ble_hrs.c是心率计程序服务的代码。


buttons_init(void)初始化两个按钮:HR_INC_BUTTON_PIN_NO和HR_DEC_BUTTON_PIN_NO,分别模拟心率计的加减。

  1. /**@brief Function for initializing the button module. 
  2.  */  
  3. static void buttons_init(void)  
  4. {  
  5.     // Configure HR_INC_BUTTON_PIN_NO and HR_DEC_BUTTON_PIN_NO as wake up buttons and also configure  
  6.     // for 'pull up' because the eval board does not have external pull up resistors connected to  
  7.     // the buttons.   
  8.     static app_button_cfg_t buttons[] =  
  9.     {  
  10.         {HR_INC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler},  
  11.         {HR_DEC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler}  // Note: This pin is also BONDMNGR_DELETE_BUTTON_PIN_NO  
  12.     };  
  13.       
  14.     APP_BUTTON_INIT(buttons, sizeof(buttons) / sizeof(buttons[0]), BUTTON_DETECTION_DELAY, false);  
  15. }  
/**@brief Function for initializing the button module.
 */
static void buttons_init(void)
{
    // Configure HR_INC_BUTTON_PIN_NO and HR_DEC_BUTTON_PIN_NO as wake up buttons and also configure
    // for 'pull up' because the eval board does not have external pull up resistors connected to
    // the buttons.
    static app_button_cfg_t buttons[] =
    {
        {HR_INC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler},
        {HR_DEC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler}  // Note: This pin is also BONDMNGR_DELETE_BUTTON_PIN_NO
    };
    
    APP_BUTTON_INIT(buttons, sizeof(buttons) / sizeof(buttons[0]), BUTTON_DETECTION_DELAY, false);
}

当按下按钮时,处理程序是button_event_handler(),它处理心率计的加减模拟:

  1. /**@brief Function for handling button events. 
  2.  * 
  3.  * @param[in]   pin_no   The pin number of the button pressed. 
  4.  */  
  5. static void button_event_handler(uint8_t pin_no, uint8_t button_action)  
  6. {  
  7.     if (button_action == APP_BUTTON_PUSH)  
  8.     {  
  9.         switch (pin_no)  
  10.         {  
  11.             case HR_INC_BUTTON_PIN_NO:  
  12.                 // Increase Heart Rate measurement  
  13.                 m_cur_heart_rate += HEART_RATE_CHANGE;  
  14.                 if (m_cur_heart_rate > MAX_HEART_RATE)  
  15.                 {  
  16.                     m_cur_heart_rate = MIN_HEART_RATE; // Loop back  
  17.                 }  
  18.                 break;  
  19.                   
  20.             case HR_DEC_BUTTON_PIN_NO:  
  21.                 // Decrease Heart Rate measurement  
  22.                 m_cur_heart_rate -= HEART_RATE_CHANGE;  
  23.                 if (m_cur_heart_rate < MIN_HEART_RATE)  
  24.                 {  
  25.                     m_cur_heart_rate = MAX_HEART_RATE; // Loop back  
  26.                 }  
  27.                 break;  
  28.                   
  29.             default:  
  30.                 APP_ERROR_HANDLER(pin_no);  
  31.                 break;  
  32.         }  
  33.     }      
  34. }  

参考资料:nRF51822 AK II上手指南(中文) 点击打开链接

 

转载:点击打开链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
s110_nrf51_8.0.0 The main features of this release are the ability to set the size of the GATT Server Attribute Table when initializing the BLE stack, the possibility for the application to be notified when the SoftDevice receives scan requests, and the ability to disable RF channels for advertising. Changes to CPU availability during radio events, DC/DC converter configuration, and PPI channel allocations have been made to take advantage of the nRF51 series IC revision 3. The BLE API has been aligned to that of the S120 SoftDevice. Notes: This is a major release which has changed the Application Programmer Interface (API), requiring applications to be recompiled. This SoftDevice version is not Production tested on all IC revisions, and is not compatible with nRF51 IC revision 1. Users of the SoftDevice must verify the compatibility of their SoftDevice/IC combination for development and for production. Compatibility information is found in the nRF51 Series Compatibility Matrix, which can be downloaded from the Nordic Semiconductor web page. SoftDevice properties The SoftDevice Specification corresponding to this release is the S110 SoftDevice Specification v2.0. This version of the SoftDevice contains the Master Boot Record (MBR) version 1.0.1. The combined MBR and SoftDevice memory requirements for this version are as follows: Flash: 96 kB (0x18000 bytes). RAM: 8 kB (0x2000 bytes) (default value - dependent upon configured size of the GATT Server Attribute Table). New functionality SoftDevice The application can now configure the amount of memory reserved for the GATT Server Attribute Table when initializing the BLE stack (DRGN-3744). Configuration is optional. By default, the RAM reserved for the Attribute Table will be 0x700 bytes. This is the same default allocation as in the S110 v7.1.0. GAP The application can now configure the SoftDevice to deliver events when scan request packets are received (DRGN-2880, NRFFOETT-281). The application can now selectively dis

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值