NRF51822自学笔记(三)心率计

依旧是官方给的例程恩……

int main(void)
{
	
    uint32_t err_code;

    timers_init();
    gpiote_init();
    buttons_init();
    ble_stack_init();
    device_manager_init();

    // Initialize Bluetooth Stack parameters.
    gap_params_init();//初始化gap层连接
    advertising_init();
    services_init();
    conn_params_init();
	

    // Start advertising.
    advertising_start();//启动定时器,battery每2S发送一次数据,heart rate每1S发送一次数据

    // 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);
    }
}

先初始化,初始化了定时器,GPIO TASK&EVENT,按钮(pin16和pin17)BLE stack,device manager,gap层连接,广播,services,和conn params(相关参数)

为啥battery每2s发送一次数据,heart rate每1s发送一次数据-。-在后面有解释

来看看初始化BLE stack的函数

static void ble_stack_init(void)
{
    uint32_t err_code;
    
    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);

    // Enable BLE stack 
    ble_enable_params_t ble_enable_params;
    memset(&ble_enable_params, 0, sizeof(ble_enable_params));
    ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
    err_code = sd_ble_enable(&ble_enable_params);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);//若event发生,进入ble_evt_dispatch
    APP_ERROR_CHECK(err_code);
    
    // Register with the SoftDevice handler module for BLE system events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);//若system event,进入sys_evt_dispatch
    APP_ERROR_CHECK(err_code);
}
若event发生,则进入ble_evt_dispatch(),追踪一下
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
    dm_ble_evt_handler(p_ble_evt);//事件处理函数
    ble_hrs_on_ble_evt(&m_hrs, p_ble_evt);//hrs service event处理函数
    ble_bas_on_ble_evt(&bas, p_ble_evt);//bas service event处理函数
    ble_conn_params_on_ble_evt(p_ble_evt);//连接相关event处理函数
    on_ble_evt(p_ble_evt);//自定义函数(亮灯灭灯等)
}
追踪一下on_ble_evt()

static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t        err_code;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            led_stop();
            
            // Initialize the current heart rate to the average of max and min values. So that
            // everytime a new connection is made, the heart rate starts from the same value.
            m_cur_heart_rate = (MAX_HEART_RATE + MIN_HEART_RATE) / 2;

            // Start timers used to generate battery and HR measurements.
            application_timers_start();

            // Start handling button presses
            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GAP_EVT_DISCONNECTED:            
            // @note Flash access may not be complete on return of this API. System attributes are now
            // stored to flash when they are updated to ensure flash access on disconnect does not
            // result in system powering off before data was successfully written.

            // Go to system-off mode, should not return from this function, wakeup will trigger
            // a reset.
            system_off_mode_enter();
            break;

        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
            {
                led_stop();
                
                nrf_gpio_cfg_sense_input(HR_INC_BUTTON_PIN_NO,
                                         BUTTON_PULL, 
                                         NRF_GPIO_PIN_SENSE_LOW);

                nrf_gpio_cfg_sense_input(HR_DEC_BUTTON_PIN_NO,
                                         BUTTON_PULL, 
                                         NRF_GPIO_PIN_SENSE_LOW);

                system_off_mode_enter();
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}
1.这个函数用了个switch语句,判断条件的定义可以在ble_gap.h中找到

enum BLE_GAP_EVTS
{
  BLE_GAP_EVT_CONNECTED  = BLE_GAP_EVT_BASE,    /**< Connection established. */
  BLE_GAP_EVT_DISCONNECTED,                     /**< Disconnected from peer. */
  BLE_GAP_EVT_CONN_PARAM_UPDATE,                /**< Connection Parameters updated. */
  BLE_GAP_EVT_SEC_PARAMS_REQUEST,               /**< Request to provide security parameters. */
  BLE_GAP_EVT_SEC_INFO_REQUEST,                 /**< Request to provide security information. */
  BLE_GAP_EVT_PASSKEY_DISPLAY,                  /**< Request to display a passkey to the user. */
  BLE_GAP_EVT_AUTH_KEY_REQUEST,                 /**< Request to provide an authentication key. */
  BLE_GAP_EVT_AUTH_STATUS,                      /**< Authentication procedure completed with status. */
  BLE_GAP_EVT_CONN_SEC_UPDATE,                  /**< Connection security updated. */
  BLE_GAP_EVT_TIMEOUT,                          /**< Timeout expired. */
  BLE_GAP_EVT_RSSI_CHANGED,                     /**< Signal strength measurement report. */
};
又是一堆枚举常量= =……

2.这个函数设置了心率的一个初始值(毕竟没装传感器,要用某些手段来试一下)

   m_cur_heart_rate = (MAX_HEART_RATE + MIN_HEART_RATE) / 2; 追踪一下宏定义发现最小值60最大值300……恩……

3.这个函数调用application_timers_start(),使刚才创建的两个timer运行。

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);
}

  0-0这就解释了一下刚才遗留的问题……为什么发送数据battery是2s一次,heart rate是1s一次。追踪一下app_timer_start()中的参数XXX_XXX_MEAS_INTERVAL

#define BATTERY_LEVEL_MEAS_INTERVAL          APP_TIMER_TICKS(2000, APP_TIMER_PRESCALER) /**< Battery level measurement interval (ticks). */

#define HEART_RATE_MEAS_INTERVAL             APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER) /**< Heart rate measurement interval (ticks). */

追踪一下APP_TIMER_TICKS(),追踪到了app_timer.h里

#define APP_TIMER_TICKS(MS, PRESCALER)
            ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000))
第一个参数是ms,第二个宏定义 =0 。so0-0问题解决

然后看看初始化按键这个函数

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()

static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    if (button_action == APP_BUTTON_PUSH)
    {
        switch (pin_no)
        {
            case HR_INC_BUTTON_PIN_NO://pin16
                // Increase Heart Rate measurement
                m_cur_heart_rate += HEART_RATE_CHANGE;
                if (m_cur_heart_rate > MAX_HEART_RATE)
                {
                    m_cur_heart_rate = MIN_HEART_RATE; // Loop back
                }
                break;
                
            case HR_DEC_BUTTON_PIN_NO://pin17
                // Decrease Heart Rate measurement
                m_cur_heart_rate -= HEART_RATE_CHANGE;
                if (m_cur_heart_rate < MIN_HEART_RATE)
                {
                    m_cur_heart_rate = MAX_HEART_RATE; // Loop back
                }
                break;
                
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }    
}
一个长且直观的按键扫描,switch判断哪个按键被按下,然后进行当前心率的加减。

通过蓝牙广播1s发送一次数据,在手机端app上显示出来(像一个迟缓的示波器= =)。



原文地址:https://www.cnblogs.com/ldgforever/p/5854106.html