CC2541之notify通知方式的介绍和使用 一、简介 本篇介绍CC2541从机端的notify通知的两种方式。 二、实验平台 协议栈版本:BLE-CC254x-1.4.0 编译软件:IAR

CC2541之notify通知方式的介绍和使用


一、简介

本篇介绍CC2541从机端的notify通知的两种方式。


二、实验平台

协议栈版本:BLE-CC254x-1.4.0

编译软件:IAR 8.20.2

硬件平台:Smart RF开发板


三、基础知识

1、简介notify通知的两种方式

答:

1)GATT_Notification

在从机代码中使用,由从机主动通知,且不需要主机发出请求和回应。



2)GATTServApp_ProcessCharCfg

在从机代码中使用,需要主机发送一次“通知请求”给从机,从机收到“通知请求”才发送通知。

实际上这个函数里依然会调用GATT_Notification这个函数。


2、什么是CCC?

答:

Client Characteristic Configuration,俗称CCC。

notify属性的特征值,会多读、写属性的特征值多一个CCC。

从机要想使用notify函数时能正常发送出数据,就必须保证CCC是被打开的。


3、CCC如何打开?

答:notify开关可由主机端或者从机端打开,但应尽量保证由主机来打开比较合适,毕竟它是“主机”,“主机“就该有主动权。

1)主机端打开(推荐)

先获取到CCC的特征值句柄,然后利用CCC的特征值句柄往CCC的特征值中写入0x0001。

参考本博客博文《CC2541之主机端获取notify数据》。


2)从机端打开(不推荐)

GATTServApp_WriteCharCfg(connHandle, simpleProfileChar4Config, 0x0001); 


注,如果上面的0x0001改为0x0000,则为关闭notify开关。


4、如何获取CCC的句柄?

答:先获取到这个CCC所属的特征值的特征值句柄,然后将该特征值句柄+1。

例如,想要获取到char6的CCC的句柄,我就必须先获取到char6的特征值句柄(参考本博客博文《CC2541之发现服务与特征值》),比如获取到的值是0x0035,则CCC的特征值句柄就是0x0036。之所以加1,是因为char6的CCC所在属性表的位置,正好在char6的特征值后面。


5、是否可以直接在主机代码中使用0x0036当做char6的CCC句柄?

答:可以,但是不推荐。

由于句柄是osal自动分配的,代码编译好之后,特征值句柄是固定的。但是一旦你在char6之前添加了一个特征值,那么char6的CCC句柄也会往后推算,这时候你的0x0036显然就没用了。

因此强烈推荐下文中使用的方法,自动获取句柄,详情自己看代码。


四、GATT_Notification范例

本范例是我自己写的,通过按下按键S1,通知出一串从0~19的20字节的数据。

此范例的前提1:已经添加好了特征值char6,并且长度为20。(参考博文《CC2541之添加特征值》)

此范例的前提2:按键可以使用。(参考博文《CC2541之按键》)


1、添加一个“char6在属性表中的偏移值”的宏(simpleGATTprofile.c中)

#define ATTRTBL_CHAR6_IDX 

可以在属性表simpleProfileAttrTbl中一个一个地数,“Characteristic Value 6”所在的正好是属性表中第18个。


2、定义一个notify函数(simpleGATTprofile.c中)

//******************************************************************************    
//name:         SimpleGATTprofile_Char6_Notify    
//introduce:    通知len长度的数据   
//parameter:    connHandle:连接句柄    
//              pValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节    
//              len:要通知的数据的长度    
//return:       none    
//******************************************************************************   
void SimpleGATTprofile_Char6_Notify( uint16 connHandle, uint8 *pValue, uint8 len)  
{  
  attHandleValueNoti_t  noti;  
  uint16 value;  
  
  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 );  
  }  

}  

3、声明函数(simpleGATTprofile.h中)//******************************************************************************    
//name:         SimpleGATTprofile_Char6_Notify    
//introduce:    通知len长度的数据   
//parameter:    connHandle:连接句柄    
//              pValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节    
//              len:要通知的数据的长度    
//return:       none    
//******************************************************************************   
extern void SimpleGATTprofile_Char6_Notify( uint16 connHandle, uint8 *pValue, uint8 len);  

4、按键中调用notify通知的函数(SimpleBLEPeripheral.c中)
static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys )  
{  
  VOID shift;  // Intentionally unreferenced parameter  

  if ( keys & HAL_KEY_SW_6 )  
  {    
    uint16 notify_Handle;   
    uint8 *p;   

    GAPRole_GetParameter( GAPROLE_CONNHANDLE, &notify_Handle);                //获取Connection Handle   

    for(uint8 i = 0; i < 20; i++)       //写一个20字节的测试缓冲区的数据  
    {  
      *(p+i) = i;  
    }  

    SimpleGATTprofile_Char6_Notify(notify_Handle, p, 20);      
  }  
}  

5、实验结果



五、GATTServApp_ProcessCharCfg使用范例

注:TI提供的SimpleBLEPeripheral项目中,在周期事件里每隔5S即读取char3值一次,并把char3的值通知出去,此时用的就是GATTServApp_ProcessCharCfg方式。

1、周期事件中不停地设置char4的值


[cpp] view plain copy


  • static void performPeriodicTask( void )   
  • {   
  •   uint8 valueToCopy;   
  •   uint8 stat;   
  •    
  •   stat = SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &valueToCopy);   
  •    
  •   if( stat == SUCCESS )   
  •   {   
  •     /*  
  •      * Call to set that value of the fourth characteristic in the profile. Note  
  •      * that if notifications of the fourth characteristic have been enabled by  
  •      * a GATT client device, then a notification will be sent every time this  
  •      * function is called.  
  •      */   
  •     SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, sizeof(uint8), &valueToCopy);   
  •   }   
  • }    



2、SimpleProfile_SetParameter中通知char4的值
[cpp] view plain copy


  • case SIMPLEPROFILE_CHAR4:  
  •   if ( len == sizeof ( uint8 ) )   
  •   {  
  •     simpleProfileChar4 = *((uint8*)value);  
  •       
  •     // See if Notification has been enabled  
  •     GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE,  
  •                                 simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),  
  •                                 INVALID_TASK_ID );  
  •   }  
  •   else  
  •   {  
  •     ret = bleInvalidRange;  
  •   }  
  •   break;  


3、实验结果


char4不停地通知着char3的值0x03。


猜你喜欢

转载自blog.csdn.net/lizhibing115/article/details/78427612
今日推荐