【nRF52840 DK测评】完善自定义服务-发送数据
<div class='showpostmsg'>## 前言上一篇文章简单介绍了如何添加自定义的BLE服务,结合官方demo,我想你应该会有更深刻的理解。这里的UUID为128位,你可以尝试将其改为16位,看看会有什么变化。接下来,我们将继续完善自定义的服务,最终实现的功能是按下开发板(从机)的按键,开发板通过蓝牙发送数据给手机(主机)。
----
## 完善代码
首先需要添加发送数据功能。如下
```c
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*函数中,添加按键对应的操作,如下代码:
```c
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。
此内容由EEWORLD论坛网友jj1989原创,如需转载或用于商业用途需征得作者同意并注明出处
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> 积累学习一下下了 挺好的,谢谢分享!期待你的大作 !有问题在论坛讨论!
页:
[1]