前言
上一篇文章介绍了上手nRF52840需要的一些准备工作,通过对官方SDK例程的学习,我想你对BLE的应用应该有了初步了解。那如何在现有代码的基础上添加自己的BLE服务呢?接下来我将以官方例程模版,带你一步步添加自己的BLE服务。
准备工作
首先按照以下顺序操作,完成相关固件的烧录。
- demo:SDK15.0.2中examples/ble_peripheral/ble_app_template
- 这里使用gcc-arm-none-eabi进行编译,所以需要先安装好交叉编译工具链,并在sdk中的Makefile.posix文件中,配置其所在路径。
- 终端中执行make命令,等待程序编译完成,如下图所示。
4. 然后执行make flash_softdevice命令,烧录蓝牙协议栈到开发版。
5. 最后执行make flash命令,烧录应用程序到开发版。烧录完成后,芯片将自动复位重启,此时可以看到LED1开始闪烁,表明程序已经跑起来了。
- 手机打开light blue软件,连接名为Nordic_Template的设备,如下图。
可以看到除了显示广播数据外,无其它服务。接下来我们将添加一个自定义的服务。
添加服务
首先来看services_init函数,
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
ret_code_t err_code;
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
/* YOUR_JOB: Add code to initialize the services used by the application.
ble_xxs_init_t xxs_init;
ble_yys_init_t yys_init;
// Initialize XXX Service.
memset(&xxs_init, 0, sizeof(xxs_init));
xxs_init.evt_handler = NULL;
xxs_init.is_xxx_notify_supported = true;
xxs_init.ble_xx_initial_value.level = 100;
err_code = ble_bas_init(&m_xxs, &xxs_init);
APP_ERROR_CHECK(err_code);
// Initialize YYY Service.
memset(&yys_init, 0, sizeof(yys_init));
yys_init.evt_handler = on_yys_evt;
yys_init.ble_yy_initial_value.counter = 0;
err_code = ble_yy_service_init(&yys_init, &yy_init);
APP_ERROR_CHECK(err_code);
*/
}
这里注释已经写得较清楚,在这里添加相应的代码即可添加蓝牙服务。这里我们添加一个128位UUID的服务,服务包含一个characteristic,其属性为notify。将实现的功能为当开发板的key1按键状态发生变化时,通知APP。代码如下:
static void services_init(void)
{
ret_code_t err_code;
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
//key state service
ble_key_state_init_t key_state_init;
memset(&key_state_init,0,sizeof(key_state_init));
key_state_init.data_handler = NULL;
err_code = ble_key_state_init(&m_key_state,&key_state_init);
APP_ERROR_CHECK(err_code);
}
具体代码的实现,可以参考SDK中的examples/ble_peripheral/ble_app_uart这个例程。
调试
接下来编译、烧录并运行,打开JLinkRTTClient,查看输出日志,出现Fatal error。如下图:
表示程序运行出错,但日志不够详细,没给出出错的原因。此时可开启DEBUG宏,然后重新编译、烧录运行,现在日志很详细了,指出了出错的原因,如下图:
提示main.c 的296行报错,错误类型为 NRF_ERROR_NO_MEM。这里添加了服务,需要设置UUID的数量,我们添加了一个服务,所以需要宏NUS_BASE_UUID设置为1。
再次编译、烧录运行,提示RAM的起始地址需要修改。如下图:
由于我们添加的服务,会单独使用一部分内存,使得留给应用程序的内存空间将减少。根据日志提示,在链接文件中修改好RAM起始地址和大小,然后再次编译并运行。此时开发版LED1开始闪烁,程序终于跑起来了,输出日志如下图:
蓝牙正在进行快速广播。
此时通过手机链接到开发版,可以看到我们刚刚添加的服务。如下图:
总结
本文简单讲解了如何添加自定义的BLE服务,具体的操作可以参考ble_app_uart例程。下一篇将介绍如何将按键状态发送给手机。