打开主菜单

谷雨文档中心 β

更改

NRF52832DK协议栈高级实验

添加7,197字节2019年8月22日 (四) 17:33
源码讲解
==== 源码讲解 ====
首先我们先定义beacon相关的数据,其中我们用户需要关注的主要有3个参数,UUID、Major以及Minor,其他的参数大家可以理解为固定的格式(格式固定,但数据内容不固定,可能有不同的厂商信息)。另外还有一个值得我们关注的数据,那就是APP_COMPANY_IDENTIFIER,如果我们定义此参数为0x004C(也就是Apple id),那么我们的基站设备就被成为iBeacon。<syntaxhighlight lang="c" line="1" start="54">
// BEACON数据
#define APP_BEACON_INFO_LENGTH 0x17 // BEACON数据总长度
APP_MEASURED_RSSI
};
</syntaxhighlight>定义好基站的数据之后,我们需要把它添加到广播数据中,那么这边唯一的疑问的就是我们应该把基站数据作为什么type来添加。 从下面的代码中,我们不难看出,基站的数据是作为p_manuf_specific_data(也就是用户自定义)数据来添加的,在Beacon数据添加的时候,大家可以看到只有company_identifier是被独立出来配置的,这里我们将其配置为apple id,所以最终我们的设备类型会是iBeacon。<syntaxhighlight lang="c" line="1" start="110">
//******************************************************************
// fn : advertising_init
==== 实验简介 ====
NUS(Nordic Uart Service)实验,他本质上是和开始的LED与按键的实验是一样的,都是新建一个服务文件,注册好我们需要使用的特征值功能,然后传输数据。不过是要比他们稍微复杂一点,因为我们串口的数据是涉及到收发两个部分(也就是既有write也有notify),所以我们在注册特征值的时候,是要注册两个,一个负责write,一个负责notify。
 
剩下的就是串口外设的处理,我们这边对于串口驱动不做介绍,大家可以去看基础实验部分的说明。我们在这个实验中仅给大家讲解串口RX收到的数据如何通知(notify)给手机,手机下发(write)的数据如何通过串口TX打印显示出来。
 
==== 硬件说明 ====
串口一向是所有开发板必需的功能之一,nRF52DK开发板采用CH340C芯片,将芯片的UART信号转换为USB接口信号,方便电脑使用USB来虚拟一个串口调试。
CH340C外围电路简单,且不需要外部晶振,nRF52DK开发板采用与Nordic官方开发板相同的串口收发引脚,如下表格所示。
{| class="wikitable"
!网络标号
!芯片引脚号
!连接方式
|-
|CH340_TX
|P0.08(nRF_RX信号)
|通过SW1拨动开关,选择连接
|-
|CH340_RX
|P0.06(nRF_TX信号)
|通过SW1拨动开关,选择连接
|}[[文件:NRF52832 CH340C虚拟串口.png|居中|无框|609x609像素|链接=http://doc.iotxx.com/%E6%96%87%E4%BB%B6:NRF52832_CH340C%E8%99%9A%E6%8B%9F%E4%B8%B2%E5%8F%A3.png]]图中P5引出了CH340C的流控制引脚,但是没有连接任何线路,所需要使用流控制,可自行连接测试。
==== 实验现象 ====
==== 源码讲解 ====
 
===== ble_nus.c\.h =====
先看下nus服务的初始化函数,首先我们还是先初始化了一个回调p_nus_init->data_handler,这个回调用于将nus层的数据传递给mian文件使用。
 
接下来我们初始化nus服务,还是和以前一样的,经过给参数的赋值,最终我们调用sd_ble_gatts_service_add函数注册了一个句柄为p_nus->service_handle的服务。
 
最后我们来注册我们需要使用的特征值characteristic,这边我们需要注册两个,一个是TX(发送),一个是RX(接收)。
 
首先我们看一下RX特征值的添加,我们配置他的属性是write,因为手机(主机)发送数据是通过write的方式;接下来我们看下TX特征值,我们做为从机设备,发送数据给手机(主机)使用的是notify方式,我们依次将这两个特征值添加到服务当中。<syntaxhighlight lang="c" line="1" start="248">
uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
{
ret_code_t err_code;
ble_uuid_t ble_uuid;
ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
ble_add_char_params_t add_char_params;
 
VERIFY_PARAM_NOT_NULL(p_nus);
VERIFY_PARAM_NOT_NULL(p_nus_init);
 
// Initialize the service structure.
p_nus->data_handler = p_nus_init->data_handler;
 
/**@snippet [Adding proprietary Service to the SoftDevice] */
// Add a custom base UUID.
err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
VERIFY_SUCCESS(err_code);
 
ble_uuid.type = p_nus->uuid_type;
ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
 
// Add the service.
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&ble_uuid,
&p_nus->service_handle);
/**@snippet [Adding proprietary Service to the SoftDevice] */
VERIFY_SUCCESS(err_code);
 
// Add the RX Characteristic.
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;
add_char_params.uuid_type = p_nus->uuid_type;
add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN;
add_char_params.init_len = sizeof(uint8_t);
add_char_params.is_var_len = true;
add_char_params.char_props.write = 1;
add_char_params.char_props.write_wo_resp = 1;
 
add_char_params.read_access = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;
 
err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
 
// Add the TX Characteristic.
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC;
add_char_params.uuid_type = p_nus->uuid_type;
add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN;
add_char_params.init_len = sizeof(uint8_t);
add_char_params.is_var_len = true;
add_char_params.char_props.notify = 1;
 
add_char_params.read_access = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;
add_char_params.cccd_write_access = SEC_OPEN;
 
return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
}
</syntaxhighlight>看完nus服务初始化之后,我们需要来看下ble_nus_on_ble_evt函数,这个函数在LED实验中有过说明,它的注册是在main文件中,我们注册nus实例的时候注册好的,功能是用来接收底层返回的GAP与GATT事件。
 
从代码中可以看到,我们这个实验需要接收的底层返回有3个<syntaxhighlight lang="c" line="1" start="218">
void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
if ((p_context == NULL) || (p_ble_evt == NULL))
{
return;
}
 
ble_nus_t * p_nus = (ble_nus_t *)p_context;
 
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
on_connect(p_nus, p_ble_evt);
break;
 
case BLE_GATTS_EVT_WRITE:
on_write(p_nus, p_ble_evt);
break;
 
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
on_hvx_tx_complete(p_nus, p_ble_evt);
break;
 
default:
// No implementation needed.
break;
}
}
</syntaxhighlight>
=== 主机NUS实验 ===
510
个编辑