【BLE-CC2640】CC2640之添加自定义服务

本篇博文最后修改时间:2017年06月02日,17:28。


一、简介

本文以SimpleBLEPeripheral工程为例,介绍如何在工程中添加一个自定义的服务


二、实验平台

协议栈版本:ble_cc26xx_2_01_00_44423

编译软件:IAR Embedded Workbench for ARM Version 7.40

硬件平台:CC26xxDK开发板

仿真器:XDS100V3(香瓜)

手机平台:小米4S

APP:BLE读写器


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:[email protected]

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
香瓜单片机之Linux群:512598061
香瓜单片机之职场交流群:450154342
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、 实验前提
1、在进行本文步骤前,请先 阅读 以下博文:
暂无

2、在进行本文步骤前,请先 实现以下博文:
暂无


五、基础知识

暂无


六、实验步骤

1、编写并添加自定义的服务

1)写一个服务源文件GUA_Profile.c(存放在“……\ble_cc26xx_2_01_00_44423\Projects\ble\SimpleBLEPeripheral\CC26xx\Source\Application\GUA”路径下)

//******************************************************************************      
//name:         GUA_profile.c      
//introduce:    香瓜自定义的服务,内含一个可读、可写、可通知的特征值  
//author:       甜甜的大香瓜    
//email:        [email protected]     
//QQ group      香瓜BLE之CC2640(557278427)   
//changetime:   2016.08.27   
//******************************************************************************  
/*********************************************************************  
 * INCLUDES  
 */  
#include 

#include "bcomdef.h"  
#include "OSAL.h"  
#include "linkdb.h"  
#include "att.h"  
#include "gatt.h"  
#include "gatt_uuid.h"  
#include "gattservapp.h"  
#include "gapbondmgr.h"  
  
#include "GUA_Profile.h"  
  
/********************************************************************* 
 * MACROS 
 */  
  
/********************************************************************* 
 * CONSTANTS 
 */  
  
#define SERVAPP_NUM_ATTR_SUPPORTED              5  
  
//属性在属性表中的偏移值  
#define ATTRTBL_GUA_CHAR1_IDX                   2  
#define ATTRTBL_GUA_CHAR1_CCC_IDX               3  
/********************************************************************* 
 * TYPEDEFS 
 */  
  
/********************************************************************* 
 * GLOBAL VARIABLES 
 */  
// GUA Service UUID: 0xFFE0  
CONST uint8 GUAServUUID[ATT_BT_UUID_SIZE] =  
{   
  LO_UINT16(GUAPROFILE_SERV_UUID), HI_UINT16(GUAPROFILE_SERV_UUID)  
};  
  
// GUA char1 UUID: 0xFFE1  
CONST uint8 GUAChar1UUID[ATT_BT_UUID_SIZE] =  
{   
  LO_UINT16(GUAPROFILE_CHAR1_UUID), HI_UINT16(GUAPROFILE_CHAR1_UUID)  
};  
  
/********************************************************************* 
 * EXTERNAL VARIABLES 
 */  
  
/********************************************************************* 
 * EXTERNAL FUNCTIONS 
 */  
  
/********************************************************************* 
 * LOCAL VARIABLES 
 */  
  
static GUAProfileCBs_t *GUAProfile_AppCBs = NULL;  
  
/********************************************************************* 
 * Profile Attributes - variables 
 */  
  
// GUA Service attribute  
static CONST gattAttrType_t GUAProfile_Service = { ATT_BT_UUID_SIZE, GUAServUUID };  
  
// GUA Characteristic 1 Properties  
static uint8 GUAProfile_Char1_Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;  
  
// GUA Characteristic 1 Value  
static uint8 GUAProfile_Char1[GUAPROFILE_CHAR1_LEN] = {0};  
  
// GUA Characteristic 1 Configs  
static gattCharCfg_t *GUAProfile_Char1_Config;  
  
// GUA Characteristic 1 User Description  
static uint8 GUAProfile_Char1_UserDesp[10] = "GUA Char1\0";  
  
  
/********************************************************************* 
 * Profile Attributes - Table 
 */  
  
static gattAttribute_t GUAProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =   
{  
  // GUA Service  
  {   
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */  
    GATT_PERMIT_READ,                         /* permissions */  
    0,                                        /* handle */  
    (uint8 *)&GUAProfile_Service                       /* pValue */  
  },  
  
    // GUA Characteristic 1 Declaration  
    {   
      { ATT_BT_UUID_SIZE, characterUUID },  
      GATT_PERMIT_READ,   
      0,  
      &GUAProfile_Char1_Props   
    },  
  
      // GUA Characteristic 1 Value  
      {   
        { ATT_BT_UUID_SIZE, GUAChar1UUID },  
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,   
        0,   
        GUAProfile_Char1  
      },  
  
      // GUA Characteristic 1 configuration  
      {   
        { ATT_BT_UUID_SIZE, clientCharCfgUUID },  
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,   
        0,   
        (uint8 *)&GUAProfile_Char1_Config   
      },  
  
      // GUA Characteristic 1 User Description  
      {   
        { ATT_BT_UUID_SIZE, charUserDescUUID },  
        GATT_PERMIT_READ,   
        0,   
        GUAProfile_Char1_UserDesp   
      },        
};  
  
  
/********************************************************************* 
 * LOCAL FUNCTIONS 
 */  
static uint8 GUAProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,   
                            uint8 *pValue, uint16 *pLen, uint16 offset, uint16 maxLen, uint8 method );  
static bStatus_t GUAProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,  
                                 uint8 *pValue, uint16 len, uint16 offset, uint8 method );  
  
/********************************************************************* 
 * PROFILE CALLBACKS 
 */  
// GUAProfile Service Callbacks  
CONST gattServiceCBs_t GUAProfileCBs =  
{  
  GUAProfile_ReadAttrCB,        // Read callback function pointer  
  GUAProfile_WriteAttrCB,       // Write callback function pointer  
  NULL                          // Authorization callback function pointer  
};  
  
/********************************************************************* 
 * PUBLIC FUNCTIONS 
 */  
  
/********************************************************************* 
 * @fn      GUAProfile_AddService 
 * 
 * @brief   Initializes the GUA service by registering 
 *          GATT attributes with the GATT server. 
 * 
 * @param   services - services to add. This is a bit map and can 
 *                     contain more than one service. 
 * 
 * @return  Success or Failure 
 */  
bStatus_t GUAProfile_AddService( uint32 services )  
{  
  uint8 status = SUCCESS;  
  
  // Allocate Client Characteristic Configuration table
  GUAProfile_Char1_Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
                                                            linkDBNumConns );
  if ( GUAProfile_Char1_Config == NULL )
  {     
    return ( bleMemAllocError );
  }
  
  // Initialize Client Characteristic Configuration attributes  
  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, GUAProfile_Char1_Config );  
    
    
  if ( services & GUAPROFILE_SERVICE )  
  {  
    // Register GATT attribute list and CBs with GATT Server App  
    status = GATTServApp_RegisterService( GUAProfileAttrTbl,   
                                          GATT_NUM_ATTRS( GUAProfileAttrTbl ), 
                                          GATT_MAX_ENCRYPT_KEY_SIZE,                                          
                                          &GUAProfileCBs );  
  }  
  
  return ( status );  
}  
  
/********************************************************************* 
 * @fn      GUAProfile_RegisterAppCBs 
 * 
 * @brief   Registers the application callback function. Only call  
 *          this function once. 
 * 
 * @param   callbacks - pointer to application callbacks. 
 * 
 * @return  SUCCESS or bleAlreadyInRequestedMode 
 */  
bStatus_t GUAProfile_RegisterAppCBs( GUAProfileCBs_t *appCallbacks )  
{  
  if ( appCallbacks )  
  {  
    GUAProfile_AppCBs = appCallbacks;  
      
    return ( SUCCESS );  
  }  
  else  
  {  
    return ( bleAlreadyInRequestedMode );  
  }  
}  
  
/********************************************************************* 
 * @fn      GUAProfile_SetParameter 
 * 
 * @brief   Set a GUA Profile parameter. 
 * 
 * @param   param - Profile parameter ID 
 * @param   len - length of data to right 
 * @param   pValue - pointer to data to write.  This is dependent on 
 *          the parameter ID and WILL be cast to the appropriate  
 *          data type (example: data type of uint16 will be cast to  
 *          uint16 pointer). 
 * 
 * @return  bStatus_t 
 */  
bStatus_t GUAProfile_SetParameter( uint8 param, uint8 len, void *pValue )  
{  
  bStatus_t ret = SUCCESS;  
  switch ( param )  
  {  
    case GUAPROFILE_CHAR1:  
      if ( len == GUAPROFILE_CHAR1_LEN )   
      {  
        VOID memcpy( GUAProfile_Char1, pValue, GUAPROFILE_CHAR1_LEN );  
      }  
      else  
      {  
        ret = bleInvalidRange;  
      }  
      break;  
      
    default:  
      ret = INVALIDPARAMETER;  
      break;  
  }  
    
  return ( ret );  
}  
  
/********************************************************************* 
 * @fn      GUAProfile_GetParameter 
 * 
 * @brief   Get a GUA Profile parameter. 
 * 
 * @param   param - Profile parameter ID 
 * @param   pValue - pointer to data to put.  This is dependent on 
 *          the parameter ID and WILL be cast to the appropriate  
 *          data type (example: data type of uint16 will be cast to  
 *          uint16 pointer). 
 * 
 * @return  bStatus_t 
 */  
bStatus_t GUAProfile_GetParameter( uint8 param, void *pValue )  
{  
  bStatus_t ret = SUCCESS;  
  switch ( param )  
  {  
    case GUAPROFILE_CHAR1:  
      VOID memcpy( pValue, GUAProfile_Char1, GUAPROFILE_CHAR1_LEN );  
      break;  
        
    default:  
      ret = INVALIDPARAMETER;  
      break;  
  }  
    
  return ( ret );  
}  
  
/********************************************************************* 
 * @fn          GUAProfile_ReadAttrCB 
 * 
 * @brief       Read an attribute. 
 * 
 * @param       connHandle - connection message was received on 
 * @param       pAttr - pointer to attribute 
 * @param       pValue - pointer to data to be read 
 * @param       pLen - length of data to be read 
 * @param       offset - offset of the first octet to be read 
 * @param       maxLen - maximum length of data to be read 
 * 
 * @return      Success or Failure 
 */  
static uint8 GUAProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,   
                            uint8 *pValue, uint16 *pLen, uint16 offset, uint16 maxLen, uint8_t method )  
{  
  bStatus_t status = SUCCESS;  
   
  // If attribute permissions require authorization to read, return error  
  if ( gattPermitAuthorRead( pAttr->permissions ) )  
  {  
    // Insufficient authorization  
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );  
  }  
    
  // Make sure it's not a blob operation (no attributes in the profile are long  
  if ( offset > 0 )  
  {  
    return ( ATT_ERR_ATTR_NOT_LONG );  
  }  
   
  if ( pAttr->type.len == ATT_BT_UUID_SIZE )  
  {  
    // 16-bit UUID  
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);  
    switch ( uuid )  
    {  
      // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;  
      // gattserverapp handles this type for reads  
  
      // GUA characteristic does not have read permissions, but because it  
      //   can be sent as a notification, it must be included here  
      case GUAPROFILE_CHAR1_UUID:  
        *pLen = GUAPROFILE_CHAR1_LEN;  
        VOID memcpy( pValue, pAttr->pValue, GUAPROFILE_CHAR1_LEN );  
        break;  
  
      default:  
        // Should never get here!  
        *pLen = 0;  
        status = ATT_ERR_ATTR_NOT_FOUND;  
        break;  
    }  
  }  
  else  
  {  
    // 128-bit UUID  
    *pLen = 0;  
    status = ATT_ERR_INVALID_HANDLE;  
  }  
  
  return ( status );  
}  
  
/********************************************************************* 
 * @fn      GUAProfile_WriteAttrCB 
 * 
 * @brief   Validate attribute data prior to a write operation 
 * 
 * @param   connHandle - connection message was received on 
 * @param   pAttr - pointer to attribute 
 * @param   pValue - pointer to data to be written 
 * @param   len - length of data 
 * @param   offset - offset of the first octet to be written 
 * 
 * @return  Success or Failure 
 */  
static bStatus_t GUAProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,  
                                 uint8 *pValue, uint16 len, uint16 offset, uint8_t method )  
{  
  bStatus_t status = SUCCESS;  
  uint8 notifyApp = 0xFF;  
    
  // If attribute permissions require authorization to write, return error  
  if ( gattPermitAuthorWrite( pAttr->permissions ) )  
  {  
    // Insufficient authorization  
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );  
  }  
    
  if ( pAttr->type.len == ATT_BT_UUID_SIZE )  
  {  
    // 16-bit UUID  
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);  
    switch ( uuid )  
    {  
      case GUAPROFILE_CHAR1_UUID:    
  
        if ( offset == 0 )    
        {    
          if ( len != GUAPROFILE_CHAR1_LEN )    
          {    
            status = ATT_ERR_INVALID_VALUE_SIZE;    
          }    
        }    
        else    
        {    
          status = ATT_ERR_ATTR_NOT_LONG;    
        }    
            
        //将接收到的数据写进特征值中,并且置标志位   
        if ( status == SUCCESS )    
        {    
          VOID memcpy( pAttr->pValue, pValue, GUAPROFILE_CHAR1_LEN );    
          notifyApp = GUAPROFILE_CHAR1;    
        }    
               
      break;    
        
      case GATT_CLIENT_CHAR_CFG_UUID:  
        //char1通道,则打开notify开关  
        if ( pAttr->handle == GUAProfileAttrTbl[ATTRTBL_GUA_CHAR1_CCC_IDX].handle )//GUA CHAR1 NOTIFY    
        {    
          status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,    
                                                   offset, GATT_CLIENT_CFG_NOTIFY );    
        }               
        else    
        {    
          status = ATT_ERR_INVALID_HANDLE;    
        }    
        break;  
         
      default:  
        status = ATT_ERR_ATTR_NOT_FOUND;  
        break;  
    }  
  }  
  else  
  {  
    // 128-bit UUID  
    status = ATT_ERR_INVALID_HANDLE;  
  }  
  
  // If a charactersitic value changed then callback function to notify application of change  
  if ( (notifyApp != 0xFF ) && GUAProfile_AppCBs && GUAProfile_AppCBs->pfnGUAProfileChange )  
  {  
    GUAProfile_AppCBs->pfnGUAProfileChange( notifyApp );    
  }   
    
  return ( status );  
}  
    
//******************************************************************************            
//name:             GUAprofile_Notify           
//introduce:        notify发送函数          
//parameter:        param:特征值通道参数  
//                  connHandle:连接句柄      
//                  cpValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节  
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜BLE之CC2640(557278427)                  
//changetime:       2016.08.27                    
//******************************************************************************   
void GUAprofile_Notify( uint8 param, uint16 connHandle, uint8 *pValue, uint8 len)    
{    
  attHandleValueNoti_t  noti;    
  uint16 value;    
    
  switch ( param )  
  {  
    //特征值1
    case GUAPROFILE_CHAR1:    
    {
      //读出CCC
      value  = GATTServApp_ReadCharCfg( connHandle, GUAProfile_Char1_Config );   
        
      //判断CCC是否被打开
      if ( value & GATT_CLIENT_CFG_NOTIFY )                                     
      {    
        //分配发送数据缓冲区
        noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI, GUAPROFILE_CHAR1_LEN, NULL); 
        
        //分配成功,则发送数据
        if(noti.pValue != NULL)
        {
          //填充数据
          noti.handle = GUAProfileAttrTbl[ATTRTBL_GUA_CHAR1_IDX].handle;    
          noti.len = len;    
          memcpy( noti.pValue, pValue, len);  
          
          //发送数据
          if (GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS)
          {
            GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
          }
        }
      }    
      break;      
    } 
  
    default:  
      break;  
  }        
}    

2)写一个服务头文件GUA_Profile.h(存放在“……\ble_cc26xx_2_01_00_44423\Projects\ble\SimpleBLEPeripheral\CC26xx\Source\Application\GUA”路径下)

//******************************************************************************      
//name:         GUA_profile.h      
//introduce:    香瓜自定义的服务,内含一个可读、可写、可通知的特征值  
//author:       甜甜的大香瓜    
//email:        [email protected]     
//QQ group      香瓜BLE之CC2640(557278427)   
//changetime:   2016.08.27   
//******************************************************************************   
#ifndef GUA_PROFILE_H  
#define GUA_PROFILE_H  
  
#ifdef __cplusplus  
extern "C"  
{  
#endif  
  
/*********************************************************************  
 * INCLUDES  
 */  
  
/********************************************************************* 
 * CONSTANTS 
 */  
  
// Profile Parameters  
#define GUAPROFILE_CHAR1                       0  // RW uint8 - Profile GUA Characteristic 1 value  
   
// GUA Service UUID  
#define GUAPROFILE_SERV_UUID                   0xFFE0  
      
// GUA CHAR1 UUID  
#define GUAPROFILE_CHAR1_UUID                  0xFFE1  
  
// GUA Profile Services bit fields  
#define GUAPROFILE_SERVICE                     0x00000001  
  
// Length of GUA Characteristic 1 in bytes  
#define GUAPROFILE_CHAR1_LEN                   20    
/********************************************************************* 
 * TYPEDEFS 
 */  
  
    
    
/********************************************************************* 
 * MACROS 
 */  
  
/********************************************************************* 
 * Profile Callbacks 
 */  
// Callback when a characteristic value has changed  
typedef void (*GUAProfileChange_t)( uint8 paramID );  
  
typedef struct  
{  
  GUAProfileChange_t        pfnGUAProfileChange;  // Called when characteristic value changes  
} GUAProfileCBs_t;  
  
/********************************************************************* 
 * API FUNCTIONS  
 */  
  
/* 
 * GUAProfile_AddService- Initializes the GUA service by registering 
 *          GATT attributes with the GATT server. 
 * 
 * @param   services - services to add. This is a bit map and can 
 *                     contain more than one service. 
 */  
  
extern bStatus_t GUAProfile_AddService( uint32 services );  
    
/* 
 * GUAProfile_RegisterAppCBs - Registers the application callback function. 
 *                    Only call this function once. 
 * 
 *    appCallbacks - pointer to application callbacks. 
 */  
extern bStatus_t GUAProfile_RegisterAppCBs( GUAProfileCBs_t *appCallbacks );  
  
/* 
 * GUAProfile_SetParameter - Set a Simple Key Profile parameter. 
 * 
 *    param - Profile parameter ID 
 *    len - length of data to right 
 *    pValue - pointer to data to write.  This is dependent on 
 *          the parameter ID and WILL be cast to the appropriate  
 *          data type (example: data type of uint16 will be cast to  
 *          uint16 pointer). 
 */  
extern bStatus_t GUAProfile_SetParameter( uint8 param, uint8 len, void *pValue );  
    
/* 
 * GUA_GetParameter - Get a Simple Key Profile parameter. 
 * 
 *    param - Profile parameter ID 
 *    pValue - pointer to data to write.  This is dependent on 
 *          the parameter ID and WILL be cast to the appropriate  
 *          data type (example: data type of uint16 will be cast to  
 *          uint16 pointer). 
 */  
extern bStatus_t GUAProfile_GetParameter( uint8 param, void *pValue );  
  
//******************************************************************************            
//name:             GUAprofile_Notify           
//introduce:        notify发送函数          
//parameter:        param:特征值通道参数  
//                  connHandle:连接句柄      
//                  cpValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节  
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜BLE之CC2640(557278427)                  
//changetime:       2016.08.27                       
extern void GUAprofile_Notify( uint8 param, uint16 connHandle, uint8 *pValue, uint8 len);  
/*********************************************************************  
*********************************************************************/  
  
#ifdef __cplusplus  
}  
#endif  
  
#endif /* GUA_PROFILE_H */  

3)工程中添加GUA_Profile.c和GUA_Profile.h

【BLE-CC2640】CC2640之添加自定义服务_第1张图片


4)在IAR设置中添加服务的文件路径

$PROJ_DIR$/../../../Source/Application/GUA    

2、在应用层中添加服务相关的代码

1)添加GUA_Profile头文件(SimpleBLEPeripheral.c中)

//香瓜  
#include "GUA_Profile.h"     
//香瓜

2)服务初始化(SimpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)

//香瓜  
  //增加服务  
  GUAProfile_AddService(GATT_ALL_SERVICES);  
  
  //初始化特征值  
  uint8 GUAProfile_Char1Value[GUAPROFILE_CHAR1_LEN] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};  
  GUAProfile_SetParameter( GUAPROFILE_CHAR1, GUAPROFILE_CHAR1_LEN, &GUAProfile_Char1Value );  
  
  //添加回调函数  
  VOID GUAProfile_RegisterAppCBs( &simpleBLEPeripheral_GUAProfileCBs );      
//香瓜  

3)定义服务的回调函数及处理函数(SimpleBLEPeripheral.c中)

//******************************************************************************            
//name:             GUAProfileChangeCB           
//introduce:        应用层香瓜服务回调函数         
//parameter:        paramID:特征值ID                  
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜BLE之CC2640(557278427)                  
//changetime:       2016.08.27                     
//****************************************************************************** 
static void GUAProfileChangeCB( uint8 paramID )  
{
  SimpleBLEPeripheral_enqueueMsg(SBP_GUA_CHAR_CHANGE_EVT, paramID);
}

//******************************************************************************            
//name:             GUA_CharValueChangeEvt           
//introduce:        应用层香瓜服务的处理函数         
//parameter:        paramID:特征值ID                  
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜BLE之CC2640(557278427)                  
//changetime:       2016.08.27                     
//****************************************************************************** 
static void GUA_CharValueChangeEvt(uint8_t paramID)
{  
  uint16 notify_Handle;     
  uint8 bBuf[20] = {0};   
  uint8 *p = bBuf;  
      
  switch( paramID )  
  {  
    case GUAPROFILE_CHAR1:     
          
      GAPRole_GetParameter( GAPROLE_CONNHANDLE, ¬ify_Handle);        //获取Connection Handle     
          
      for(uint8 i = 0; i < 20; i++)                                     //写一个20字节的测试缓冲区的数据    
      {    
        *(p+i) = i;    
      }    
      
      GUAprofile_Notify(GUAPROFILE_CHAR1, notify_Handle, p, 20);        
  
      break;  
  
    default:  
      // should not reach here!  
      break;  
  }  
}  
里面添加了测试代码,一旦接收到数据,就把0~19发给主机。


4)声明服务的回调函数和处理函数(SimpleBLEPeripheral.c中)

//香瓜  
static void GUAProfileChangeCB( uint8 paramID );  
static void GUA_CharValueChangeEvt(uint8_t paramID);
//香瓜

5)注册回调函数(SimpleBLEPeripheral.c中)

//香瓜  
// GUA Profile Callbacks  
static GUAProfileCBs_t simpleBLEPeripheral_GUAProfileCBs =  
{  
  GUAProfileChangeCB    // Charactersitic value change callback  
};  
//香瓜 

6)添加香瓜服务处理事件(SimpleBLEPeripheral.c中)

①添加香瓜服务处理事件的宏定义

#define SBP_GUA_CHAR_CHANGE_EVT               0x0010

②添加香瓜服务处理事件的处理部分(替换SimpleBLEPeripheral.c中的SimpleBLEPeripheral_processAppMsg函数

static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
{
  switch (pMsg->hdr.event)
  {
    case SBP_STATE_CHANGE_EVT:
      SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->
                                                hdr.state);
      break;

    case SBP_CHAR_CHANGE_EVT:
      SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);
      break;

    case SBP_GUA_CHAR_CHANGE_EVT:
      GUA_CharValueChangeEvt(pMsg->hdr.state);
      break;
      
    default:
      // Do nothing.
      break;
  }
}

七、注意事项

手机可能缓存了之前的代码(在更新过CC2541的代码之后,都需要清除手机端的缓存!!!),因此要清除缓存,清除缓存的方法如下:

方法一:关闭app、关闭蓝牙总开关、打开蓝牙总开关、打开app。
方法二:手机重启。


八、实验结果

注:香瓜在开发CC2541时常用的truthblue在读取特征值时会出错,比如char1(0x01)却读到7、8个字节的乱数据,暂用蓝牙读写器代替。

【BLE-CC2640】CC2640之添加自定义服务_第2张图片


【BLE-CC2640】CC2640之添加自定义服务_第3张图片

【BLE-CC2640】CC2640之添加自定义服务_第4张图片
可见上图实现了使用香瓜服务中的特征值进行的收发,因此本文步骤实验成功。


你可能感兴趣的:(BLE-CC2640)