nrf52832 学习笔记蓝牙从机Proflies开发
Posted 不咸不要钱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙从机Proflies开发相关的知识,希望对你有一定的参考价值。
nrf52832 学习笔记(八)蓝牙从机Proflies开发
所谓开发蓝牙应用程序,其实就是开发service和characteristic。通过API,添加自己需要的characteristic和service,你自己的蓝牙设备就诞生了。只要characteristic和service是符合GATT规范的,你可以随意添加任何characteristic和service,并将他们组合成一个专门的蓝牙设备。由于这个蓝牙设备是按照规范来定义的,所以它可以与任何其他蓝牙设备,比如手机,互联互通,并完成所要求的的交互动作。
这里的蓝牙设备,我们还可以进一步细分为蓝牙profile设备和非profile蓝牙设备。profile就是一个子规范,蓝牙profile设备包含的所有实际service和characteristic都是按照profile规格来添加和定义的,比如说心率计profile,就是一个蓝牙联盟定义的蓝牙设备,蓝牙联盟有一份专门的spec来定义心率计profile,在这份spec中规定了心率计profile除了包含心率service,还包含电池service,设备信息service等。
从这可以看出,心率profile和心率service是包含关系,前者包含后者。Nordic开发了很多蓝牙profile应用,如果你的应用就是一个profile,那么可以完全使用这些现成的例子而不做任何修改,这样做还有一个好处:BQB认证流程将大为简化,你只需做一些文档声明工作,不再需要出具测试报告,就可以获得BQB认证证书。
如果要使用Nordic 编写的profile 需要在SDK中使能对应的服务
以便开启代码中的宏定义
这里强调一下,如果你的设备没有完全按照心率profile来,但也包含心率service,这个时候你就不能说你的设备是一个心率profile设备,虽然你的设备不是心率profile设备,但是它提供的功能基本上跟心率profile设备差不多,因为它包含心率service。这种情况下,你的设备还是一个标准的蓝牙设备,还是可以去过BQB认证的,而且过BQB认证的流程也不复杂,就是比profile设备多了一个自测报告而已。这种设备跟手机通信,是没有任何兼容性或者互联互通问题的。最后强调一下,目前大部分人开发的蓝牙应用程序,其实都是非profile蓝牙应用程序(也叫私有proflie设备),比如手环、共享单车、蓝牙透传等。
添加UUID
UUID 为2字节或者16字节长。在BLE中我们使用UUID来定义数据的类型,UUID是128 bit的,所以我们有足够的UUID来表达万事万物。其中有一个UUID非常特殊,它被蓝牙联盟采用为官方UUID,这个UUID如下所示:
由于这个UUID众所周知,蓝牙联盟将自己定义的attribute或者数据只用16bit UUID来表示,比如0x1234,其实它也是128bit,完整表示为:
使用公共UUID
在Nordic SDK中,如果想要使用SIG定义的服务,例如心跳服务,可以使用如下宏定义初始化UUID
ble_uuid_t ble_uuid;
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_HEART_RATE_SERVICE);
添加自定义UUID
在Nordic SDK中,如果想要使用自定义的服务,需要添加自定义UUID
#define LBS_UUID_BASE 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, \\
0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x01, 0x01
#define LBS_UUID_SERVICE 0x1523
ble_uuid_t ble_uuid;
uint8_t uuid_type;
ble_uuid128_t base_uuid = LBS_UUID_BASE;
//添加自定义UUID
err_code = sd_ble_uuid_vs_add(&base_uuid, &uuid_type);
VERIFY_SUCCESS(err_code);
ble_uuid.type = uuid_type;
ble_uuid.uuid = LBS_UUID_SERVICE;
添加服务
蓝牙中的数据根据ATT和GATT协议,可以看成如下表格,添加服务其实就是如下图添加了一列数据,数据类型为Primary Service
//添加服务
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_lbs->service_handle);
VERIFY_SUCCESS(err_code);
添加特征
蓝牙中的数据根据ATT和GATT协议,可以看成如下表格,添加特征其实就是如下图在服务列下添加特征列数据:
应用层可以对特征(Characteristic)进行读、写、通知、指示操作。以下以SDK中 ble_app_blinky例子说明
uint32_t ble_lbs_init(ble_lbs_t * p_lbs, const ble_lbs_init_t * p_lbs_init)
uint32_t err_code;
ble_uuid_t ble_uuid;
ble_add_char_params_t add_char_params;
// Initialize service structure.
p_lbs->led_write_handler = p_lbs_init->led_write_handler;
// 添加UUID
ble_uuid128_t base_uuid = LBS_UUID_BASE;
err_code = sd_ble_uuid_vs_add(&base_uuid, &p_lbs->uuid_type);
VERIFY_SUCCESS(err_code);
ble_uuid.type = p_lbs->uuid_type;
ble_uuid.uuid = LBS_UUID_SERVICE;
//添加服务
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_lbs->service_handle);
VERIFY_SUCCESS(err_code);
// 添加按键特征
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = LBS_UUID_BUTTON_CHAR; //UUID
add_char_params.uuid_type = p_lbs->uuid_type; //UUID类型,根据类型可以还原出128bit的UUID
add_char_params.init_len = sizeof(uint8_t); //参数初始长度
add_char_params.max_len = sizeof(uint8_t); //参数最大长度
add_char_params.char_props.read = 1; //允许读
add_char_params.char_props.notify = 1; //允许通知
add_char_params.read_access = SEC_OPEN; //读权限,如果配对绑定中开启了MITM,可以使用MITM
add_char_params.cccd_write_access = SEC_OPEN; //通知权限
// 添加按键描述符
ble_add_char_user_desc_t add_char_desc;
memset(&add_char_desc, 0, sizeof(add_char_desc));
add_char_desc.max_size = 32; //描述符最大长度
add_char_desc.size = 32; //描述符长度
add_char_desc.char_props.read = 1; //可读
add_char_desc.read_access = SEC_OPEN; //读权限
add_char_desc.p_char_user_desc = (uint8_t *)"button"; //描述符
add_char_params.p_user_descr = &add_char_desc;
err_code = characteristic_add(p_lbs->service_handle,
&add_char_params,
&p_lbs->button_char_handles);
if (err_code != NRF_SUCCESS)
return err_code;
// 添加LED特征
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = LBS_UUID_LED_CHAR; //UUID
add_char_params.uuid_type = p_lbs->uuid_type; //UUID类型,根据类型可以还原出128bit的UUID
add_char_params.init_len = sizeof(uint8_t); //参数初始长度
add_char_params.max_len = sizeof(uint8_t); //参数最大长度
add_char_params.char_props.read = 1; //允许读
add_char_params.char_props.write = 1; //允许写
add_char_params.read_access = SEC_OPEN; //读权限
add_char_params.write_access = SEC_OPEN; //写权限
return characteristic_add(p_lbs->service_handle, &add_char_params, &p_lbs->led_char_handles);
读
客户端读取服务端数据。
写
客户端将数据写入给服务端。写的时候需要在回调函数中处理
通知
服务端数据上报给客户端,注意不是任何时候服务端都可以上报的,需要客户使能了服务端的CCCD,服务端才可以上报给客户端。
当按键按下时,使用如下API即可将按键状态通知给客户端。
uint32_t ble_lbs_on_button_change(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t button_state)
ble_gatts_hvx_params_t params;
uint16_t len = sizeof(button_state);
memset(¶ms, 0, sizeof(params));
params.type = BLE_GATT_HVX_NOTIFICATION;
params.handle = p_lbs->button_char_handles.value_handle;
params.p_data = &button_state;
params.p_len = &len;
return sd_ble_gatts_hvx(conn_handle, ¶ms);
以上是关于nrf52832 学习笔记蓝牙从机Proflies开发的主要内容,如果未能解决你的问题,请参考以下文章