前言:
SDK版本15.3
评估板:pca10040
在uart的例程中添加battery service
添加之前,手机连上设备之后扫描到的service如下:
一、分配ram空间
softdevice的flash code是确定,但ram是不确定,和sevice的多少以及以下几个宏有关:
- #define NRF_SDH_BLE_TOTAL_LINK_COUNT 1 //一共同时可以支持多少个连接,使用默认值即可
- #define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 //作为从模式的连接同时能有几个,使用默认值即可
- #define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0 //作为主模式的连接同时能有几个,使用默认值即可
- #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247 // MTU 值的大小,使用默认值即可,nrf51 系列中 mtu 的默认值为23
- #define NRF_SDH_BLE_VS_UUID_COUNT 1 //用户自定义的base UUID有几个,使用默认值即可,因为例程中的uart service 使用了一个的128bit的 uuid ,所以这是 count 值为1。因为此次实验添加的是自有 service ,所以 base uuid 只有uart service 一个。每添加一个 base uuid , count 值就+1,同时每增加一个uuid,IRAM1的起始地址就要增加0x10,size 同时减少0x10。
- #define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408 //Attribute table总共占多少协议栈RAM空间,该值必须是4的倍数。
- #define NRF_SDH_BLE_SERVICE_CHANGED 0 //要不要包含service change characteristic,使用默认值即可
二、代码修改
2.1 添加文件
- 添加service文件,文件路径为..\..\..\..\..\..\components\ble\ble_services\ble_bas
- 添加sensorsim文件(此文件只是为了演示电量变化而添加的传感器数据模拟器,正式项目可以不用加),文件路径为..\..\..\..\..\..\components\libraries\sensorsim
该文件需要在keil的工程配置文件中设置文件路径才可以使用:
2.2 配置sdk_config.h文件
- 使能bas service
2.3 添加头文件
在main.c文件中添加
- #include "ble_bas.h"
- #include "sensorsim.h"(此文件只是为了演示电量变化而添加的传感器数据模拟器,正式项目可以不用加)
2.4 添加bas实例
在main.c文件中添加实例
BLE_BAS_DEF(m_bas); /**< Structure used to identify the battery service. */
2.5 bas service初始化
在services_init(void) api中添加以下代码:
ble_bas_init_t bas_init;
// Initialize Battery Service.
memset(&bas_init, 0, sizeof(bas_init));
bas_init.evt_handler = NULL;
bas_init.support_notification = true;
bas_init.p_report_ref = NULL;
bas_init.initial_batt_level = 100;
// Here the sec level for the Battery Service can be changed/increased.
bas_init.bl_rd_sec = SEC_OPEN;
bas_init.bl_cccd_wr_sec = SEC_OPEN;
bas_init.bl_report_rd_sec = SEC_OPEN;
err_code = ble_bas_init(&m_bas, &bas_init);
APP_ERROR_CHECK(err_code);
到此为止,手机已经可以正常查询到设备的 bsa service了。
以下为使用 sensorsim 功能模拟设备的电量变化并主动上报
2.6 添加变量和宏定义
#define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(2000) /**< Battery level measurement interval (ticks). */
#define MIN_BATTERY_LEVEL 81 /**< Minimum simulated battery level. */
#define MAX_BATTERY_LEVEL 100 /**< Maximum simulated 7battery level. */
#define BATTERY_LEVEL_INCREMENT 1 /**< Increment between each simulated battery level measurement. */
APP_TIMER_DEF(m_battery_timer_id); /**< Battery timer. */
static sensorsim_cfg_t m_battery_sim_cfg; /**< Battery Level sensor simulator configuration. */
static sensorsim_state_t m_battery_sim_state; /**< Battery Level sensor simulator state. */
2.7 在main(void)中添加 sensor simulator 初始化和 timers start
sensor_simulator_init();
application_timers_start();
2.8 添加battery定时器
- 在 timers_init() api中添加以下代码
// 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);
- 添加battery_level_meas_timeout_handler(void * p_context) api
/**@brief Function for handling the Battery measurement timer timeout.
*
* @details This function will be called each time the battery level measurement timer expires.
*
* @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_level_update();
}
- 添加battery_level_update(void) api
/**@brief Function for performing battery measurement and updating the Battery Level characteristic
* in Battery Service.
*/
static void battery_level_update(void)
{
ret_code_t err_code;
uint8_t battery_level;
battery_level = (uint8_t)sensorsim_measure(&m_battery_sim_state, &m_battery_sim_cfg);
err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL);
if ((err_code != NRF_SUCCESS) &&
(err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_BUSY) &&
(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
)
{
APP_ERROR_HANDLER(err_code);
}
}
三、测试
经过以上操作就可以在手机端使用bas service了。