前言
上一篇文章简单介绍了如何添加自定义的BLE服务,结合官方demo,我想你应该会有更深刻的理解。这里的UUID为128位,你可以尝试将其改为16位,看看会有什么变化。接下来,我们将继续完善自定义的服务,最终实现的功能是按下开发板(从机)的按键,开发板通过蓝牙发送数据给手机(主机)。
完善代码
首先需要添加发送数据功能。如下
uint32_t ble_key_state_data_send(ble_key_state_t * p_key_state,
uint8_t * p_data,
uint16_t * p_length,
uint16_t conn_handle)
{
ret_code_t err_code;
ble_gatts_hvx_params_t hvx_params;
ble_key_state_client_context_t * p_client;
VERIFY_PARAM_NOT_NULL(p_key_state);
err_code = blcm_link_ctx_get(p_key_state->p_link_ctx_storage, conn_handle, (void *) &p_client);
VERIFY_SUCCESS(err_code);
if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
{
return NRF_ERROR_NOT_FOUND;
}
if (!p_client->is_notification_enabled)
{
return NRF_ERROR_INVALID_STATE;
}
if (*p_length > BLE_KEY_STATE_MAX_DATA_LEN)
{
return NRF_ERROR_INVALID_PARAM;
}
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_key_state->tx_handles.value_handle;
hvx_params.p_data = p_data;
hvx_params.p_len = p_length;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
return sd_ble_gatts_hvx(conn_handle, &hvx_params);
}
注意这里首先要判断是否有连接,然后判断是否使能了notify,否则服务器(从机)不知道将数据发往哪里。
然后在bsp_event_handler函数中,添加按键对应的操作,如下代码:
static void bsp_event_handler(bsp_event_t event)
{
ret_code_t err_code;
static uint8_t key1_state=0x00;
uint16_t len = 1;
switch (event)
{
case BSP_EVENT_KEY_0:
do{
key1_state = 0x01;
err_code = ble_key_state_data_send(&m_key_state,&key1_state,&len,m_conn_handle);
if ((err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_NOT_FOUND))
{
APP_ERROR_CHECK(err_code);
}
} while (err_code == NRF_ERROR_RESOURCES);
break;
......
......
}
}
这里BSP_EVENT_KEY_0对应开发板上的Button1,当Button1按下时,将调用ble_key_state_data_send函数,发送数据0x01,长度为1个字节。
调试
编译、烧录并运行,LED1开始闪烁,表明程序运行正常。打开lightblue,连接开发板,使能notify。如下图:
图1
此时按下Button1,手机立即收到了0x01,与期望的一致。但是过一会儿,手机显示断开连接。如下图:
图2
再看一下开发板,LED1仍然常亮,代码似乎卡住了。
检查一下代码,未发现异常,log中也未显示异常,看来只能跟踪调试一下。这里使用SES调试,重复之前的操作,发现程序跑飞了。在发送数据的代码处打断点,最终发现在
on_hvx_tx_complete函数的最后一行,会调用
p_key_state->data_handler(&evt);而在
services_init()函数中,data_handler被初始化成了NULL。由于这里发送完数据后,不需要执行其它操作,所以初始化的时候设置为了NULL。解决这个问题最简单的方法是注释掉这段代码,不进行回调。或者是在初始化的时候,给data_handler分配一个有效的回调函数地址。
再次编译、烧录并运行,按下按键,数据发送成功,再次按下按键,手机再次收到数据,如下图:
图3
总结
通过本篇和上一篇文章的介绍,我们完成了一个自定义BLE服务的添加,并实现了从机往主机的数据发送。在此基础上,你可以尝试实现主机往从机的数据发送,具体实现可参考SDK中的ble_app_uart例程。下一篇文章将带大家了解一下BLE Mesh。