依旧是官方给的例程恩……
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上显示出来(像一个迟缓的示波器= =)。