打开主菜单

谷雨文档中心 β

更改

NRF52832DK协议栈实验

添加6,594字节2019年7月26日 (五) 11:13
NUS服务获取实验
==== 实验简介 ====
经过之前的学习,我们已经完成了蓝牙的广播、扫描、连接,并且知道了如何更新MTU以及连接参数。
 
那么当前我们仅剩下的便是连接之后的通信了,谈到蓝牙的通信,那么我们必然是绕不开蓝牙的服务的。
 
这一章节我们便给大家介绍一下从机设备如何注册一个服务,以及主机设备如何去获取服务,这一实验我们仅从应用层给大家介绍服务的添加及获取,具体的服务的实现,我们将在以后的实验中再给大家介绍。
==== 实验现象 ====
主机上电之后,首先扫描并打印符合过滤的从机设备信息,然后发起连接,连接成功之后打印连接参数、连接句柄(connhanlde)等信息。
 
当连接完成之后,首先更新了MTU大小,然后就去发起服务的扫描,最终实验现象上体现的就是发现完成,成功通过NUS(Nordic UART Service)连接到设备。
[[文件:Nrf rtt 19.png|边框|居中|无框|648x648像素]]
从机设备上电广播,当被主机连接之后,会打印主机的设备信息以及连接参数,最终会打印更新后的MTU大小。
[[文件:Nrf tft 29.png|边框|居中|无框|657x657像素]]
==== 工程及源码讲解 ====
 
===== 主机部分 =====
主机部分主要有两点需要我们关注一下,一个是MTU大小为什么会是244,另一个就是我们本实验的重点,如何去发起对服务的发现。
 
====== gatt_init()函数 ======
首先我们看一下MTU大小的配置,我们可以先进入nrf_ble_gatt_init()初始化函数中,可以看到p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE这样的一个参数赋值,我们再前往查看NRF_SDH_BLE_GATT_MAX_MTU_SIZE的数值,可以看到在sdh_config.h文件中,我们将其定义为247,然后我们再减去NUS的3字节占用,所以实验现象中打印的Data len是244。<syntaxhighlight lang="c" line="1" start="226">
//******************************************************************
// fn : gatt_init
//
// brief : 初始化GATT
//
// param : none
//
// return : none
void gatt_init(void)
{
ret_code_t err_code;
 
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
APP_ERROR_CHECK(err_code);
}
</syntaxhighlight>
 
====== nus_c_init()函数 ======
这个主机的nus client初始化函数,其在ble_nus_c_init()函数中,最终去发起了对服务的发现。然后我们定义了一个回调函数,用于处理服务发现和服务处理的事件。<syntaxhighlight lang="c" line="1" start="279">
//******************************************************************
// fn : nus_c_init
//
// brief : 初始化NUS客户端(Nordic UART Service client)
//
// param : none
//
// return : none
static void nus_c_init(void)
{
ret_code_t err_code;
ble_nus_c_init_t init;
 
init.evt_handler = ble_nus_c_evt_handler;
 
err_code = ble_nus_c_init(&m_ble_nus_c, &init);
APP_ERROR_CHECK(err_code);
}
</syntaxhighlight>
 
====== ble_nus_c_evt_handler()函数 ======
NUS服务相关的回调函数,这个回调中包含了3个事件ID。
 
BLE_NUS_C_EVT_DISCOVERY_COMPLETE:服务发现完成,这个事件返回之后,我们需要调用ble_nus_c_handles_assign()函数给服务分配handle,然后调用ble_nus_c_tx_notif_enable()函数使能NUS服务的TX特征值的通知。
 
BLE_NUS_C_EVT_NUS_TX_EVT:NUS服务的TX特征值事件,这个事件返回,代表了TX特征值有数据通知到来。
 
BLE_NUS_C_EVT_DISCONNECTED:NUS断开事件,服务获取异常断开。<syntaxhighlight lang="c" line="1" start="242">
//******************************************************************
// fn : ble_nus_c_evt_handler
//
// brief : NUS事件
//
// param : none
//
// return : none
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
ret_code_t err_code;
 
switch (p_ble_nus_evt->evt_type)
{
case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
NRF_LOG_INFO("Discovery complete.");
err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
APP_ERROR_CHECK(err_code);
 
err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("Connected to device with Nordic UART Service.");
break;
 
case BLE_NUS_C_EVT_NUS_TX_EVT:
NRF_LOG_DEBUG("Receiving data.");
NRF_LOG_HEXDUMP_DEBUG(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;
 
case BLE_NUS_C_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected.");
break;
default:
break;
}
}
</syntaxhighlight>
 
===== 从机部分 =====
从机部分有关MTU 244的初始化和主机部分相同,这边不再重复,我们主要关注一下NUS服务的初始化注册。
 
====== services_init()函数 ======
服务初始化函数中,我们调用ble_nus_init()函数初始化了NUS服务,这样初始化完成之后,我们从机的服务列表中,就会将NUS添加。
 
并且我们定义了一个nus_data_handler()回调函数,用于处理NUS服务的事件(这个回调的事件我们本章节用不到,所以我们这边先不介绍,留着下一章节讲解)。<syntaxhighlight lang="c" line="1" start="223">
//******************************************************************
// fn : services_init
//
// brief : 初始化服务(本例程展示NUS:Nordic Uart Service)
//
// param : none
//
// return : none
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
 
// Initialize NUS.
memset(&nus_init, 0, sizeof(nus_init));
 
nus_init.data_handler = nus_data_handler;
 
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
}
</syntaxhighlight>
==== 实验总结 ====
经过j这一章节的学习,大家需要了解的要点如下:
 
1、从机如何初始化注册一个服务,不仅仅是NUS,包含了协议栈SDK中的已有的服务
 
2、主机如何去发起对连接的从机的服务的发现
 
3、了解服务相关的回调函数中的事件的含义
=== NUS通信实验 ===
==== 实验简介 ====
上一章节,我们已经学习过了如何注册和发现一个服务,那么这一章节,我们将给大家介绍,如何利用这个服务去完成通信。
 
服务中的特征值的属性分为如下4种:Write写、Read读、Notify通知、Indicate暗示。
 
这边我们只给大家介绍Write与Notify,Write属性是主机向从机写,Notify属性是从机通知主机(通知属性的作用与否,需要由主机获取服务后使能)。
==== 实验现象 ====
510
个编辑