[蓝牙] 3、 剖析BLE心率检测工程
位于:<KEIL path> \ARM\Device\Nordic\nrf51822\Board\pca10001\s110\ble_app_hrs

Heart Rate Example
The Heart Rate Application is a firmware example that implements the Heart Rate profile using the hardware delivered in the nRF51822 Development Kit.
The source code and project file can be found in the <InstallFolder>\Nordic\nrf51822\Board\nrf6310\s110\ble_app_hrs folder.
The application includes the two services in the Heart Rate profile:
In addition, use of the Battery Service is also demonstrated.
When the application starts, three timers are started which control generation of various parts of the Heart Rate Measurement characteristic value:
- Heart Rate
- RR Interval
- Sensor Contact Detected
Also, a timer for generating battery measurements is started.
The sensor measurements are simulated the following way:
- Heart Rate: See Sensor Data Simulator.
- RR Interval: See Sensor Data Simulator.
- Sensor Contact: The state is toggled each time the timer expires.
- Battery Level: See Sensor Data Simulator.
When notification of Heart Rate Measurement characteristic is enabled, the Heart Rate Measurement, containing the current value for all the components of the Heart Rate Measurement characteristic, is notified each time the Heart Rate measurement timer expires. When notification of Battery Level characteristic is enabled, the Battery Level is notified each time the Battery Level measurement timer expires.
- Note
- This application is not power optimised!
- The application will stop advertising after 3 minutes and go to system-off mode. Push the button 0 restart advertising.
Setup
Instructions on how to set up the nRFgo Motherboard: nRFgo Motherboard Setup (nRF6310).
LED assignments:
- LED 0: Advertising
- LED 1: Connected
- LED 7: Asserted (i.e. an assert check in the application has failed)
Buttons assignments:
- Button 0: Wake-up from system-off and restart advertising.
- Button 1: Wake-up erase all bonds and restart advertising.
Testing
The Heart Rate Application can be tested using the nRF Utility app for iOS and Android. The app will be listed as "nRFready Utility" on Apple Store and as "nRF Utility" on Google Play.
It can also be tested using the Master Control Panel as follows:
- Compile and program the application. Observe that the Advertising LED is lit.
- Connect to the device from Master Control Panel (the device will be advertising as 'Nordic_HRM'), then perform service discovery. Observe that the Connected LED is lit, and the Advertising LED is off.
- Click the 'Enable services' button on the Master Control Panel. Observe that Heart Rate notifications are received every second, and Battery Level notifications are received every two seconds.
main函数
int main(void)
{
uint32_t err_code; timers_init();//@details Initializes the timer module. This creates and starts application timers.
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 ad->for loop
Timer初始化
/**@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。
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
/**@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后时钟开始运行:
/**@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
/**@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, , sizeof(hrs_init)); hrs_init.evt_handler = hrs_event_handler;
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, , 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 = ; err_code = ble_bas_init(&bas, &bas_init);
APP_ERROR_CHECK(err_code); // Initialize Device Information Service
memset(&dis_init, , 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的结构定义:
/**@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是心率计程序服务的代码。
/** @file
*
* @defgroup ble_sdk_srv_hrs Heart Rate Service
* @{
* @ingroup ble_sdk_srv
* @brief Heart Rate Service module.
*
* @details This module implements执行 the Heart Rate Service with the Heart Rate Measurement,
* Body Sensor Location and Heart Rate Control Point characteristics.
* During initialization it adds the Heart Rate Service and Heart Rate Measurement
* characteristic to the BLE stack database. Optionally it also adds the
* Body Sensor Location and Heart Rate Control Point characteristics.
*
* If enabled, notification of the Heart Rate Measurement characteristic is performed
* when the application calls ble_hrs_heart_rate_measurement_send().
*
* The Heart Rate Service also provides a set of functions for manipulating the
* various fields in the Heart Rate Measurement characteristic, as well as setting
* the Body Sensor Location characteristic value.
*
* If an event handler is supplied by the application, the Heart Rate Service will
* generate Heart Rate Service events to the application.
*
* @note The application must propagate BLE stack events to the Heart Rate Service module by calling
* ble_hrs_on_ble_evt() from the from the @ref ble_stack_handler callback.
*
* @note Attention!
* To maintain compliance with Nordic Semiconductor ASA Bluetooth profile
* qualification listings, this section of source code must not be modified.
*/
buttons_init(void)初始化两个按钮:HR_INC_BUTTON_PIN_NO和HR_DEC_BUTTON_PIN_NO,分别模拟心率计的加减。
/**@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[]), BUTTON_DETECTION_DELAY, false);
}
当按下按钮时,处理程序是button_event_handler(),它处理心率计的加减模拟:
/**@brief Function for handling button events.
*
* @param[in] pin_no The pin number of the button pressed.
*/
static void button_event_handler(uint8_t pin_no)
{
switch (pin_no)
{
case HR_INC_BUTTON_PIN_NO:
// 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:
// 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;
}
}
注:
本篇讲了整个工程的大致结构
[蓝牙] 2、蓝牙BLE协议及架构浅析&&基于广播超时待机说广播事件
@beautifulzzzz 2015-12-13 continue~
[蓝牙] 3、 剖析BLE心率检测工程的更多相关文章
- [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)
开机初始化Log Log编号 函数名 所在文件名 000001: main ..\main.c 000002: timers_init ..\main.c 000003: gpiote_init ...
- 蓝牙4.0 BLE基础之vdd检测new
外部ADC通道,我们现在用的是A0脚,也就是P00通道 把它设置成输出的一个模式.在程序中设置,代码如下: #include <ioCC2540.h> #define HAL_ADC_RE ...
- 蓝牙4.0 BLE入门
在BLE协议中有两个角色,一个是周边(Periphery),另外一个是中央(Central).一个中央可以同时连接多个周边,但一个周边某一时刻只能连接一个中央.但是不管periphery还是centr ...
- 如何实现蓝牙空中升级BLE OTA
如何实现BLE OTA?什么叫DFU?如何通过UART实现固件升级?又如何通过USB实现固件升级?怎么保证升级的安全性?什么叫双备份(dual bank)DFU?什么叫单备份(single bank) ...
- 蓝牙4.0 BLE 开发
在BLE开发中的一些随记,供大家参考: 凡事皆有状态 低功耗蓝牙背后有个基本的概念:任何事务都有状态.状态可以是任何东西:当前的温度,设备里电池的状态,设备名称或者对测量温度的地点的描述.它通过属性服 ...
- 蓝牙4.0 BLE 广播包解析
在使用EN-Dongle捕获和解析广播包之前,我们先了解一下BLE报文的结构,之后,再对捕获的广播包进行分析.在学习BLE的时候,下面两个文档是极其重要的,这是SIG发布的蓝牙的核心协议和核心协议增补 ...
- Android 蓝牙4.0 BLE
Android ble (Bluetooth Low Energy) 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用. BLE是蓝牙4.0的核心Profil ...
- android蓝牙4.0(BLE)开发之ibeacon初步
一个april beacon里携带的信息如下 ? 1 <code class=" hljs ">0201061AFF4C0002159069BDB88C11416BAC ...
- IOS学习之蓝牙4.0 BLE
IOS学习也一段时间了,该上点干货了.前段时间研究了一下IOS蓝牙通讯相关的东西,把研究的一个成果给大家分享一下. 一 项目背景 简单介绍一下做的东西,设备是一个金融刷卡器,通过蓝牙与iphone手机 ...
随机推荐
- spring知识大全(4)
5 Spring对事务的支持 一.AOP事务的含义: 事务当作一个切面,动态地织入到目标对象,形成一个代理对象. 二.Spring的事务机制 Spring支持声明式事务. Spring使用事务服务代理 ...
- Groovy 处理 XML
1. Parsing XML 1.1. XmlParser and XmlSlurper The most commonly used approach for parsing XML with Gr ...
- python基础第三天(1)
函数 函数分为:内置函数,自定义函数,导入函数. 内置函数 python为咱们提供的快捷方式 vars()---针对脚本的,找到这个脚本中的所有变量. #!/usr/bin/env python # ...
- jsp页面输入小写金额转大写
<script> function chineseNumber(num){ if (isNaN(num) || num > Math.pow(10, 12)) return &quo ...
- comet4j
简介 准备工作 下载服务端jar文件 下载客户端js文件 修改服务器配置文件 在web.xml中加载Comet4J框架 客户端使用简介 JS.Engine.start方法 JS.Engine.stop ...
- js 字符串格式化方法
String.prototype.format = function(args) { var result = this; if (arguments.length > 0) { if (arg ...
- listener监听器
前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和 ...
- Java实现Excel导入数据库,数据库中的数据导入到Excel
private static void executeMethod(JobExecutionContext arg0) throws Exception{ try { TContrastService ...
- Windows Phone 8.1 新特性 - 控件之列表选择控件
本篇我们来介绍Windows Phone 8.1 新特性中的列表选择控件. 在Windows Phone 8 时代,大家都会使用 LongListSelector 来实现列表选择控件,对数据进行分组显 ...
- 黑马程序员-NSDictionary和NSMutableDictionary
NSDictionary和NSMutableDictionary:通过key和value进行对应,进行存储元素,能够方便提取所需的元素.key是不能够重复出现,但是value能够重复出现.NSDict ...