打印
[其他]

(转)MM32W无线MCU系列产品应用笔记 —— 自定义服务和特...

[复制链接]
3930|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
MM32W0x2xxB 蓝牙功能协议栈目前以Lib 形式提供,用户通过调用相关接口的方式实现对应功能。例程中,用户如需调整BLE 数据交互的特征值、服务及数据的收发,可按照如下的几个步骤进行调整,大部分的配置都在..\SRC_LIB\app.c文件中。

蓝牙之间通信是以参数来进行数据传输,即服务端定好一个参数,客户端可以对这个参数进行读,写,通知等操作,这个东西我们称之为特征值(characteristic),但一个参数不够我们用,比如我们这个特征值是电量的值,另一个特征值是设备读取的温度值。那这时候会有多个特征值,并且我们还会对它们分类,分出来的类我们称之为服务(service)。一个设备可以有多个服务,每一个服务可以包含多个特征值,本章节将介绍如何在例程中调整服务及自定义特征值。

使用特权

评论回复
沙发
两只袜子|  楼主 | 2021-7-19 09:39 | 只看该作者

使用特权

评论回复
板凳
两只袜子|  楼主 | 2021-7-19 09:43 | 只看该作者
分别修改const BLE_CHAR AttCharList[]和const BLE_UUID128 AttUuid128List[]中的数据,自行分配句柄(递增,不得重复)



1、type16 为database 每个记录的类型,具体取值根据蓝牙规范定义;

常用的三个宏定义:

#define TYPE_CHAR 0x2803  //特征值的声明

#define TYPE_CFG 0x2902  //客户端特征值配置描述符

#define TYPE_INFO 0x2901  //特征值用户描述符

使用特权

评论回复
地板
两只袜子|  楼主 | 2021-7-19 09:45 | 只看该作者

使用特权

评论回复
5
两只袜子|  楼主 | 2021-7-19 09:52 | 只看该作者
4、uuid128_idx 表示uuid2 的格式,如该值为UUID16_FORMAT(0xFF) 则表示uuid2 为16bit 格式,反之则表示uuid2 为128Bit 的uuid 信息对应的索引值,该索引值对应于AttUuid128List 的内容索引。uuid128 为小端格式保存。UUID就是通用唯一识别码。在蓝牙协议栈中可能会有多个服务,每个服务会有多个特征值,而这些服务或者特征值都有一个唯一的ID,这样就可以区分了。这个UUID是其他设备设置蓝牙服务和特征值的唯一方法。



应答Primary Service 的查询

下一步要修改的是att_server_rdByGrType函数。

使用特权

评论回复
6
两只袜子|  楼主 | 2021-7-19 09:53 | 只看该作者
在函数中缺省情况下如果客户对Device Info 不做特别修改,可直接调用缺省函数att_server_rdByGrTypeRspDeviceInfo(pdu_type)即可。



而下面的att_server_rdByGrTypeRspPrimaryService()需要按照上面的定义填充对应的数据,其中start_hd 与end_hd 为对应Service handle 取值范围,uuid 为字符串,对应的长度由uuidlen给出。



写操作

            当外界发来相关数据时,ser_write_rsp()函数将被调用。

            void ser_write_rsp(       u8 pdu_type/*reserved*/,

            u8 attOpcode/*reserved*/,

            u16 att_hd,  //对应特征值句柄

            u8* attValue, //数据内容指针

            u8 valueLen_w) //数据长度

使用特权

评论回复
7
两只袜子|  楼主 | 2021-7-19 09:54 | 只看该作者
通过判断特征值句柄att_hd,就可以进一步处理收到的数据。



若特征值属性为ATT_CHAR_PROP_W,需要调用ser_write_rsp_pkt()函数对这次写操作进行应答,不应答会导致连接断开。



若特征值无效或未定义,则使用att_notFd()函数进行应答,参数直接引用回调函数对应参数即可。



其中att_hd 为从手机BLE 传(写)过来数据对应的特征值的句柄,数据内容保存在变量attValue 中,数据长度为valueLen_w。

使用特权

评论回复
8
两只袜子|  楼主 | 2021-7-19 09:54 | 只看该作者
读操作

类似写操作,收到读取特征值请求时,ser_write_rsp()函数将被调用。

void server_rd_rsp(u8 attOpcode, u16 attHandle, u8 pdu_type)

通过判断attHandle来执行对应操作,使用att_server_rd()函数进行应答。

void att_server_rd(unsigned char pdu_type,

unsigned char attOpcode

unsigned short att_hd,   //对应特征值句柄

unsigned char* attValue,  //应答数据指针

unsigned char datalen );  //数据长度

使用特权

评论回复
9
两只袜子|  楼主 | 2021-7-19 09:56 | 只看该作者
其中pdu_type和attOpcode直接引用回调函数中对应参数,每次调用发送的数据长度不得超过20字节。



同写操作,若特征值无效或未定义,则使用att_notFd()函数进行应答。



Notify 数据发送操作

在模块出厂时烧录的例程中,可以通过UART的AT指令,调用Notify数据透传,对应的接口函数是



u8 sconn_notifydata(u8* data, u8 len);

使用特权

评论回复
10
两只袜子|  楼主 | 2021-7-19 09:57 | 只看该作者
原则上数据长度可以超过20 字节,协议会自动拆包发送,每个分包最大20字节,推荐一次发送的数据尽量不超过3 个分包,该函数返回实际发送的数据长度。这一函数没有指定对应的句柄,如果用户定义了多个Notify特征值,需要在发送前使用set_notifyhandle()函数指定对应的句柄,或者直接修改变量u16 cur_notifyhandle。



下面我们以在例程中添加一个可读可写的特征值为例,最后通过手机app与BLE之间进行通信:



1、在const BLE_CHAR AttCharList[]数组最后添加

{TYPE_CHAR,0x1A,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W, 0x1B,0,0,0,4},

//User defined



即在原数组最后句柄0x19后添加新的特征值,对应特征值设置可读可写,句柄0x001B为用户自定义特征值,128位UUID,索引值为4;

使用特权

评论回复
11
两只袜子|  楼主 | 2021-7-19 09:59 | 只看该作者
2、在const BLE_UUID128 AttUuid128List[]数组最后添加对应的UUID

{0x9e,0xca,0x0dc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,5,0,0x40,0x6e}, //idx4,little endian, Test



3、修改att_server_rdByGrType()函数:

att_server_rdByGrTypeRspPrimaryService(pdu_type,0x10,0x1B,(u8*)(AttUuid128List[0].uuid128),16);

修改最后的句柄值。

使用特权

评论回复
12
两只袜子|  楼主 | 2021-7-19 10:00 | 只看该作者
4、修改ser_write_rsp()函数

在switch(att_hd)分支中加入

case 0x1B:

moduleOutData("Write_Server_1B\r\n",17);   

ser_write_rsp_pkt(pdu_type);

break;

使用特权

评论回复
13
两只袜子|  楼主 | 2021-7-19 10:03 | 只看该作者
5、修改server_rd_rsp()函数

在switch(attHandle)分支中加入

case 0x1B:

moduleOutData("Read_Server_1B\r\n",17);   

att_server_rd( pdu_type, attOpcode, attHandle, "RD_SERVE_1B", 11);

break;



如下图,程序下载运行后,我们用手机连接模块,可以看到在服务列表最后多出了一项Unknown Characteristic ,可读可写,点击读按钮,可以收到字符串” RD_SERVE_1B”,UART串口输出”Read_Server_1B”,点击写按钮发送任意值会UART串口输出”Write_Server_1B”。


图1 手机端截图



图2 UART输出




使用特权

评论回复
14
两只袜子|  楼主 | 2021-7-19 10:03 | 只看该作者
5、修改server_rd_rsp()函数

在switch(attHandle)分支中加入

case 0x1B:

moduleOutData("Read_Server_1B\r\n",17);   

att_server_rd( pdu_type, attOpcode, attHandle, "RD_SERVE_1B", 11);

break;



如下图,程序下载运行后,我们用手机连接模块,可以看到在服务列表最后多出了一项Unknown Characteristic ,可读可写,点击读按钮,可以收到字符串” RD_SERVE_1B”,UART串口输出”Read_Server_1B”,点击写按钮发送任意值会UART串口输出”Write_Server_1B”。


图1 手机端截图



图2 UART输出




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2055

主题

7460

帖子

10

粉丝