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