TI BLE CC2541 关于Notification的设置及应用

本文详细解析了蓝牙设备间使用Notification进行数据交互的过程。包括从机端Profile配置、初始化、主动通知,以及主机端获取Handle、开启通知和接收数据的具体步骤。深入探讨了GATT_Client_Char_Cfg_UUID的作用和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:

https://blog.youkuaiyun.com/ab198604/article/details/50173307

一、修改从机端代码(Server端):

A 对Profile的修改

如果要使用Notification或Indification方法,必须在Profile中添加configuration,如下:

其中, clientCharCfgUUID值如下,它是uint16类型的值,具体表示为GATT_CLIENT_CHAR_CFG_UUID宏的值

#define GATT_CLIENT_CHAR_CFG_UUID 0x2902 

 

说白了,上面在profile中添加的configuration的UUID为GATT_CLIENT_CHAR_CFG_UUID (0x2902),主机若一搜到就知道它指的是什么了(当然是notification)

需要主机的client端对它进行打开通知操作后,从机才能notification通知到主机client.

 

B 初始化这个client配置特征表

当然是调用这个了。不过在例程中并不是直接调用,而是在回调函数中被执行调用。

上面这个函数是个回调函数,它是在下面函数中注册的。

linkDB_Register()函数中,simpleProfile_HandleConnStatusCB作为参数进行注册。

下面看看linkDB_Register接口的含义:

也就是说当底层的链路连接状态发生变化时回调函数就会被执行,也就是说,如果未来主从建立连接,断开连接等状态,此回调函数就会被触发,而在回调中继续执行client配置表的初始化操作。

虽然过程比较曲折,不过最终目标是执行了初始化。

 

 

C Client端需要打开Server端的Notification通知功能。

这里当然不是讲在client如何打开这个通知。而是Server端在接收到这个打开通知请求后的处理流程。需要弄明白以下几个问题:

(1)client什么时候打开这个通知? ---anytime.... 一般连接建立后,根据具体的业务,找到它的Handle后直接打开

(2)client通过什么方式打开?  ----当然是要发数据包了,当然是发write命令

(3)client对什么write? ----- 还记得上面提到的GATT_CLIENT_CHAR_CFG_UUID(0x2902)吗?通过这个UUID找到它的HANDLE,然后对这个Handle进行写操作。

 

上面几个问题弄几白了,后面思路就清楚了,既然是对Server进行write,那么Server的Write回调将会被执行。

TI CC2541软件开发指南中有如下英文描述,上面执行的代码就是打开通知。GATT_CLIENT_CFG_NOTIY宏为0x0001

 

一旦操作成功后,如果Server要想主动的给Client发数据,只需要调用SimpleProfile_SetParameter方法即可。

 

D Server端主动通知Client

下面来看看这个方法的实现:

 

如果是操作CHAR4,则会调用GATTServApp_ProcessCharCfg()方法,这是一个间接的notification方式。

 

注:上面代码中最好加入是否添加NOTIFICATION开关通知的判断,如果client没有打开,则不允许主动通知

value  = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar6Config );//读出CCC的值  

  

  if ( value & GATT_CLIENT_CFG_NOTIFY ) //判断是否打开通知开关,打开了则发送数据  

  {  

    noti.handle = simpleProfileAttrTbl[ATTRTBL_CHAR6_IDX].handle;  

    noti.len = len;  

    osal_memcpy( noti.value, pValue, len);       //数据  

    GATT_Notification( connHandle, &noti, FALSE );  

  }  

 

 

E Server端实例演示,代码如下:

 

 

 

 

二、修改主机端代码(Client)

A 通过Server端Client Config的UUID获取其Handle

使用接口GATT_DiscCharsByUUID()来获取相应的Handle

 

B 开启Notification功能

使用接口GATT_WriteCharValue

前期先通过A操作获取到对应的Handle,这个handle一般是characteristic value的handle+1,句柄的顺序是characteristic declaration, characteristic  value, 然后是 CCC.

CCC是指Client Characteristic Configuration 的这个descriptor.

下面是个例子:

 

 

 

attWriteReq_t writeReq;

 

writeReq.handle = 0x002f;

 

writeReq.len = 2;

 

writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY);        // 0x01      【1:开启Notification    0:关闭Notify】

 

writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY);          // 0x00     【1:开启Indification    0:关闭Indi】

 

writeReq.sig = 0;

 

writeReq.cmd = 0;

 

GATT_WriteCharValue( simpleBLEConnHandle, &writeReq, simpleBLETaskId );

 

 

 

C 接收来自Server的Notification消息

当Client端接收到来自对方的消息,系统会产生一个事件GATT_MSG_EVENT告之,

方法如下:

static void simpleBLECentralProcessGATTMsg( gattMsgEvent_t *pMsg )所有通过蓝牙发送的数据都会让GATT这个函数来处理.因此,发送的数据就到这里了。gattMsgEvent_t是个很大的联合体代码中都有注释,只要找到相应的结构体就行了。

 

typedef union

{

  // Request messages

  attExchangeMTUReq_t exchangeMTUReq;              //!< ATT Exchange MTU Request

  attFindInfoReq_t findInfoReq;                    //!< ATT Find Information Request

  attFindByTypeValueReq_t findByTypeValueReq;      //!< ATT Find By Type Vaue Request

  attReadByTypeReq_t readByTypeReq;                //!< ATT Read By Type Request

  attReadReq_t readReq;                            //!< ATT Read Request

  attReadBlobReq_t readBlobReq;                    //!< ATT Read Blob Request

  attReadMultiReq_t readMultiReq;                  //!< ATT Read Multiple Request

  attReadByGrpTypeReq_t readByGrpTypeReq;          //!< ATT Read By Group Type Request

  attWriteReq_t writeReq;                          //!< ATT Write Request

  attPrepareWriteReq_t prepareWriteReq;            //!< ATT Prepare Write Request

  attExecuteWriteReq_t executeWriteReq;            //!< ATT Execute Write Request

  gattReadByTypeReq_t gattReadByTypeReq;           //!< GATT Read By Type Request

  gattWriteLongReq_t gattWriteLongReq;             //!< GATT Long Write Request

  gattReliableWritesReq_t gattReliableWritesReq;   //!< GATT Reliable Writes Request

 

  // Response messages

  attErrorRsp_t errorRsp;                          //!< ATT Error Response

  attExchangeMTURsp_t exchangeMTURsp;              //!< ATT Exchange MTU Response

 

股市奇才17年不亏之谜,方法令人意想不到....

东正金融 · 燨燚

 

 

 

ThomasWangqiang: 大神能稍微讲解下Notification和Indification 的区别(主机是否回confirm(确认))在代码中如何体现(2年前#1楼)

GATT_Notification vs. GATTServApp_ProcessCharCfg

 2277

 

GATT_Notification GATTServApp_ProcessCharCfg 来自:   Ayworld

【IoT】TI BLE 主从机数据交互过程-蓝牙 Notification 方式

 3004

 

1、Notification与Indication的区别 GATT_Indication: 从机通知主机后,主机需要调用simpleprofile_writeattrcb,读取从机的数据。 GAT... 来自:       简一商业

cc2541之Notification

 834

 

从机给主机发送数据有两种方式: 第一种:通过GATT_Notification()这个函数来通知主机。 第二种:通过GATTServApp_ProcessCharCfg()这个函数通知主机。 简介这... 来自:    happygrilclh的博客

 

各种通用蓝牙UUID列表

 4423

 

var uuids = { "0001": "SDP", "0003": "RFCOMM", "0005": "TCS-BIN", "0007": "ATT", ... 来自:       Xanthuim的博客

---------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值