1平台条件
《1》软件平台:simplelink_cc13x2_26x2_sdk_3_30_00_03
《2》硬件平台:CC26X2
2 .c文件
用到4个特征值
/*********************************************************************
* INCLUDES
*/
#include "service_init.h"
#include "simple_uart.h"
#include "in_flash_manage.h"
#include "ble_data.h"
#include "ble_center.h"
#include "simple_peripheral_oad_onchip.h"
static ProfileCBs_t *Profile_AppCBs = NULL;
// step 1
/**********************************************************************************************/
//============ uuid 赋值==================
// Simple GATT Profile Service UUID: 0xFFF0
uint8 FExx_PrimaServUUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(PRIMA_SERV_UUID), HI_UINT16(PRIMA_SERV_UUID)
};
// Characteristic 1 UUID: 0xFFF1
uint8 FFx1_UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(FEx1_UUID), HI_UINT16(FEx1_UUID)
};
// Characteristic 2 UUID: 0xFFF2
uint8 FFx2_UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(FEx2_UUID), HI_UINT16(FEx2_UUID)
};
// Characteristic 3 UUID: 0xFFF3
uint8 FFx3_UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(FEx3_UUID), HI_UINT16(FEx3_UUID)
};
// Characteristic 4 UUID: 0xFFF4
uint8 FFx4_UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(FEx4_UUID), HI_UINT16(FEx4_UUID)
};
static CONST gattAttrType_t Profile_Service = { ATT_BT_UUID_SIZE, FExx_PrimaServUUID };
/********************************************************************************************************/
// step 2:通道特征
//================FEx1 通道==========================================
// Properties
static uint8 FEx1_Props = GATT_PROP_NOTIFY;
static uint8 FEx1_char_valu[BLE_SEND_LEN];// Value
static gattCharCfg_t *FEx1_Config;
static uint8 FEx1_UserDesp[17] = "rx_data";// User Description
//================FEx2通道========================================
// Properties
static uint8 FEx2_Props = GATT_PROP_WRITE_NO_RSP;
static uint8 FEx2_char_valu[BLE_SEND_LEN] = { 0, 0, 0, 0, 0 };
static uint8 FEX2_UserDesp[17] = "tx_data";
//==================FEx3 通道=======================================
// Properties
static uint8 FEx3_Props = GATT_PROP_NOTIFY;
static uint8 FEx3_char_valu[BLE_SEND_LEN];// Value
static gattCharCfg_t *FEx3_Config;
static uint8 FEx3_UserDesp[17] = "rx_at_cmd";//
//==================FEx4通道===========================================
// Properties
static uint8 FEx4_Props = GATT_PROP_WRITE_NO_RSP;
static uint8 FEx4_char_valu[BLE_SEND_LEN] = { 0, 0, 0, 0, 0 };
static uint8 FEX4_UserDesp[17] = "tx_at_cmd";
uint8_t ble_write_len=0;
/*********************************************************************
* Profile Attributes - Tabled 属性表
*/
static gattAttribute_t ProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
// Simple Profile Service
{
{ ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8 *)&Profile_Service /* pValue */
},
/************************ FEX1 *******************************/
// Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&FEx1_Props
},
// Characteristic Value
{
{ ATT_BT_UUID_SIZE, FFx1_UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
FEx1_char_valu
},
// Characteristic configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&FEx1_Config
},
// Characteristic User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
FEx1_UserDesp
},
/***********************************FEX2 *******************/
// Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&FEx2_Props
},
// Characteristic Value
{
{ ATT_BT_UUID_SIZE, FFx2_UUID },
GATT_PERMIT_WRITE,
0,
FEx2_char_valu
},
// User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
FEX2_UserDesp
},
/************************ FEX3 *******************************/
// Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&FEx3_Props
},
// Characteristic Value 9
{
{ ATT_BT_UUID_SIZE, FFx3_UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
FEx3_char_valu
},
// Characteristic configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&FEx3_Config
},
// Characteristic User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
FEx3_UserDesp
},
/***********************************FEX4 *******************/
// Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&FEx4_Props
},
// Characteristic Value
{
{ ATT_BT_UUID_SIZE, FFx4_UUID },
GATT_PERMIT_WRITE,
0,
FEx4_char_valu
},
// User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
FEX4_UserDesp
},
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t Profile_ReadAttrCB(uint16_t connHandle,
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen,
uint16_t offset, uint16_t maxLen,
uint8_t method);
static bStatus_t Profile_WriteAttrCB(uint16_t connHandle,
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len,
uint16_t offset, uint8_t method);
CONST gattServiceCBs_t ProfileCBs =
{
Profile_ReadAttrCB, // Read callback function pointer
Profile_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************
*
* @ 注册app 服务
*/
bStatus_t Profile_AddService( uint32 services )
{
uint8 status;
/************************* fex1 cccd *************************************************************/
FEx1_Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
MAX_NUM_BLE_CONNS );
if ( FEx1_Config == NULL )
{
return ( bleMemAllocError );
}
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, FEx1_Config );
/************************* fex3 cccd *************************************************************/
FEx3_Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
MAX_NUM_BLE_CONNS );
if ( FEx3_Config == NULL )
{
return ( bleMemAllocError );
}
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, FEx3_Config );
//服务初始化
if ( services & PROFILE_SERVICE )
{
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService( ProfileAttrTbl,
GATT_NUM_ATTRS(ProfileAttrTbl ),
GATT_MAX_ENCRYPT_KEY_SIZE,
&ProfileCBs );
}
else
{
status = SUCCESS;
}
return ( status );
}
//*********************************************************************
// 注册 app
bStatus_t Profile_RegisterAppCBs(ProfileCBs_t *appCallbacks )
{
if ( appCallbacks )
{
Profile_AppCBs = appCallbacks;
return ( SUCCESS );
}
else
{
return ( bleAlreadyInRequestedMode );
}
}
// *********************************************************************
// 设置 uuid
uint8 check_err =0;
bStatus_t Profile_SetParameter( uint8 param, uint8 len, void *value )
{
bStatus_t ret = SUCCESS;
switch ( param )
{
case CHAR_FEx1_ID:
if ( len <=BLE_SEND_LEN )
{
memcpy(FEx1_char_valu,(uint8 *)value,len);
// See if Notification has been enabled
check_err = GATTServApp_ProcessCharCfg( FEx1_Config, FEx1_char_valu, FALSE,
ProfileAttrTbl, GATT_NUM_ATTRS( ProfileAttrTbl ),
INVALID_TASK_ID, Profile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
case CHAR_FEx2_ID:
if ( len <= BLE_SEND_LEN )
{
VOID memcpy(FEx2_char_valu, value, BLE_SEND_LEN );
}
else
{
ret = bleInvalidRange;
}
break;
case CHAR_FEx3_ID:
if ( len <=BLE_SEND_LEN )
{
memcpy(FEx3_char_valu,(uint8 *)value,len);
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( FEx3_Config, FEx3_char_valu, FALSE,
ProfileAttrTbl, GATT_NUM_ATTRS( ProfileAttrTbl ),
INVALID_TASK_ID, Profile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
case CHAR_FEx4_ID:
if ( len <= BLE_SEND_LEN )
{
VOID memcpy(FEx4_char_valu, value, BLE_SEND_LEN );
}
else
{
ret = bleInvalidRange;
}
break;
default:
ret = INVALIDPARAMETER;
break;
}
return ( ret );
}
//*********************************************************************
// 得到特征值数据---
bStatus_t Profile_GetParameter( uint8 param, void *value )
{
bStatus_t ret = SUCCESS;
switch ( param )
{
case CHAR_FEx1_ID:
*((uint8*)value) = FEx1_char_valu[0];
break;
case CHAR_FEx2_ID:
VOID memcpy( value,FEx2_char_valu, ble_write_len );
break;
case CHAR_FEx3_ID:
*((uint8*)value) = FEx3_char_valu[0];
break;
case CHAR_FEx4_ID:
VOID memcpy( value,FEx4_char_valu, ble_write_len );
break;
default:
ret = INVALIDPARAMETER;
break;
}
return ( ret );
}
/**********************************************************************/
//特征值读取操作
static bStatus_t Profile_ReadAttrCB(uint16_t connHandle,
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen,
uint16_t offset, uint16_t maxLen,
uint8_t method)
{
bStatus_t status = SUCCESS;
// 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]);
if(uuid==FEx1_UUID)
{
*pLen = BLE_SEND_LEN;
pValue[0] = *pAttr->pValue;
}
else if(uuid==FEx2_UUID)
{
*pLen = BLE_SEND_LEN;
VOID memcpy( pValue, pAttr->pValue, BLE_SEND_LEN );
}
else if(uuid==FEx3_UUID)
{
*pLen = BLE_SEND_LEN;
VOID memcpy( pValue, pAttr->pValue, BLE_SEND_LEN );
}
else if(uuid==FEx4_UUID)
{
*pLen = BLE_SEND_LEN;
VOID memcpy( pValue, pAttr->pValue, BLE_SEND_LEN );
}
else
{
*pLen = 0;
status = ATT_ERR_ATTR_NOT_FOUND;
}
}
else
{
// 128-bit UUID
*pLen = 0;
status = ATT_ERR_INVALID_HANDLE;
}
return ( status );
}
//*********************************************************************
//特征值写操作和notify
uint8 uuid_data[20] ;
uint16 write_uuid= 0;
static bStatus_t Profile_WriteAttrCB(uint16_t connHandle,
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len,
uint16_t offset, uint8_t method)
{
bStatus_t status = SUCCESS;
uint8 notifyApp = 0xFF;
write_uuid= 0;
if ( pAttr->type.len == ATT_BT_UUID_SIZE )
{
// 16-bit UUID
write_uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(write_uuid==GATT_CLIENT_CHAR_CFG_UUID) // cccf 打开notify开关
{
status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
offset, GATT_CLIENT_CFG_NOTIFY );
ble_uart_send_data("cccfg\r\n",6);
}
/************************************** fex2通道写入函数 ****************************************************************/
if(write_uuid== FEx2_UUID )
{
if ( offset == 0 )
{
if ( len <= BLE_SEND_LEN )
{
ble_write_len= len;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if ( status == SUCCESS )
{
VOID osal_memcpy( pAttr->pValue, pValue, ble_write_len );
if( pAttr->pValue == FEx2_char_valu)
notifyApp = CHAR_FEx2_ID;
}
else
{
// Should never get here! (characteristics 2 and 4 do not have write permissions)
status = ATT_ERR_ATTR_NOT_FOUND;
}
}
/************************************** fex4通道写入函数 ****************************************************************/
if(write_uuid== FEx4_UUID )
{
if ( offset == 0 )
{
if ( len <= BLE_SEND_LEN )
{
// status = ATT_ERR_INVALID_VALUE_SIZE;
ble_write_len= len;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if ( status == SUCCESS )
{
VOID osal_memcpy( pAttr->pValue, pValue, ble_write_len );
if( pAttr->pValue == FEx4_char_valu)
notifyApp = CHAR_FEx4_ID;
}
else
{
// Should never get here! (characteristics 2 and 4 do not have write permissions)
status = ATT_ERR_ATTR_NOT_FOUND;
}
}
}
else
{
// 128-bit UUID
// const uint8 uuid[ATT_UUID_SIZE] =
// {
// BLE_BASE_UUID_128(BUILD_UINT16( pAttr->type.uuid[12], pAttr->type.uuid[13]))
// };
}
// If a characteristic value changed then callback function to notify application of change
if ( (notifyApp != 0xFF ) && Profile_AppCBs && Profile_AppCBs->pfn_ProfileChange )
{
Profile_AppCBs->pfn_ProfileChange( notifyApp );
}
return ( status );
}
/***************************************************************
*
* 从机 app写入数据函数
*/
uint8 ble_data[300];
extern status_t SimplePeripheral_enqueueMsg(uint8_t event, void *pData);
static void Peripheral_charValueChangeCB(uint8_t paramId)
{
switch(paramId)
{
case CHAR_FEx2_ID:
Profile_GetParameter(CHAR_FEx2_ID, ble_data);
ble_queue_data_in(ble_data,ble_write_len,MASTER_SPP);
break;
case CHAR_FEx4_ID:
Profile_GetParameter(CHAR_FEx4_ID, ble_data);
ble_queue_data_in(ble_data,ble_write_len,MASTER_AT);
break;
default:
// should not reach here!
break;
}
return ;
}
// Simple GATT Profile Callbacks
static ProfileCBs_t Peripheral_simpleProfileCBs =
{
Peripheral_charValueChangeCB // Characteristic value change callback
};
/******************************************
*
* @ 用户私有服务初始化
*/
void user_serv_init(void)
{
Profile_AddService(GATT_ALL_SERVICES);
uint8_t char_Value[20] = { 1, 2, 3, 4, 5 ,6,4,8,6,1,8};
Profile_SetParameter(CHAR_FEx1_ID,sizeof(char_Value),char_Value);
Profile_SetParameter(CHAR_FEx2_ID, sizeof(char_Value),char_Value);
Profile_SetParameter(CHAR_FEx3_ID, sizeof(char_Value),char_Value);
Profile_SetParameter(CHAR_FEx4_ID, sizeof(char_Value),char_Value);
Profile_RegisterAppCBs(&Peripheral_simpleProfileCBs);
}
将user_serv_init放在
3.h文件
#ifndef service_init_h_
#define service_init_h_
#include "_hal_types.h"
#include "bcomdef.h"
#include <string.h>
#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"
#include "simple_gatt_profile.h"
#ifdef SYSCFG
#include "ti_ble_config.h"
#endif
// 0x0000fee0-0000-1000-8000-00805f9b34fb -----逆序过来
#define BLE_BASE_UUID_128( uuid ) 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, \
0x00, 0x10, 0x00, 0x00, LO_UINT16( uuid ), HI_UINT16( uuid ), 0x00, 0x00
// prima----uuid
#define PRIMA_SERV_UUID 0xFEE0
// char uuid
#define FEx1_UUID 0xFEE0
#define FEx2_UUID 0xFEE1
#define FEx3_UUID 0xFEE2
#define FEx4_UUID 0xFEE3
#define SERVAPP_NUM_ATTR_SUPPORTED 15// 属性表大小
//属性在属性表中的偏移值 cc偏移值
#define ATTRTBL_FEx1_IDX 2
#define ATTRTBL_FEx1_CCC_IDX 3
//属性在属性表中的偏移值 ccfg
#define ATTRTBL_FEx3_IDX 9
#define ATTRTBL_FEx3_CCC_IDX 11
// step 3
// Profile Parameters
#define CHAR_FEx1_ID 0 //
#define CHAR_FEx2_ID 1 //
#define CHAR_FEx3_ID 2 //
#define CHAR_FEx4_ID 3 //
// Simple Keys Profile Services bit fields
#define PROFILE_SERVICE 0x00000001
// Length of Characteristic 5 in bytes
#define BLE_SEND_LEN 247
// 服务事件--------------
#define SP_CHAR_CHANGE_EVT 0x41
extern uint8 FExx_PrimaServUUID[ATT_BT_UUID_SIZE];
// Callback when a characteristic value has changed
typedef void (*ProfileChange_t)( uint8 paramID );
typedef struct
{
ProfileChange_t pfn_ProfileChange; // Called when characteristic value changes
} ProfileCBs_t;
/*********************************************************************
* API FUNCTIONS
*/
extern bStatus_t Profile_AddService( uint32 services );
extern bStatus_t Profile_RegisterAppCBs( ProfileCBs_t *appCallbacks );
extern bStatus_t Profile_SetParameter( uint8 param, uint8 len, void *value );
extern bStatus_t Profile_GetParameter( uint8 param, void *value );
void user_serv_init(void);
uint16_t get_ble_conncet_handle(void);
void start_uart_time_ms(bool type);
uint16_t ble_send_data(uint8_t *dataout,uint16_t len,uint16_t max_len,uint8 role);
uint16_t FEx3_send_data(uint8_t *dataout,uint16_t len,uint16_t max_len,bool is_spp);
uint8 is_ble_conn_state(void);
#endif
4 send data函数
/*****************************************************************
*
* Send_Notify 函数 高类聚-低耦合
* @param: CHAR_FEx1_ID(通道一) ----CHAR_FEx3_ID(通道三)
*/
void ble_Send_Notify( uint8 param, uint8 *pValue, uint8 len)
{
attHandleValueNoti_t noti;
uint16 value;
uint16 Conn_Handle=0;
Conn_Handle = connList[get_currt_conn_num()-1].connHandle;
// 通道1
if(CHAR_FEx1_ID==param)
{
value = GATTServApp_ReadCharCfg( Conn_Handle, FEx1_Config);//读出CCC
}
else
{
value = GATTServApp_ReadCharCfg( Conn_Handle, FEx3_Config);//读出CCC
}
//判断CCC是否被打开
if ( value & GATT_CLIENT_CFG_NOTIFY )
{
//分配发送数据缓冲区
noti.pValue = GATT_bm_alloc(Conn_Handle, ATT_HANDLE_VALUE_NOTI, BLE_SEND_LEN, NULL);
//分配成功,则发送数据
if(noti.pValue != NULL)
{
if(CHAR_FEx1_ID==param) // 通道1
noti.handle = ProfileAttrTbl[ATTRTBL_FEx1_IDX].handle;
else
noti.handle = ProfileAttrTbl[ATTRTBL_FEx3_IDX].handle;
noti.len = len;
memcpy( noti.pValue, pValue, len); //填充数据
//发送数据
if (GATT_Notification(Conn_Handle, ¬i, FALSE) != SUCCESS)
{
// ble_uart_send_data("notif6",6);
GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
return;
}
}
}
}
可以加入QQ群:687360507
与大伙沟通交流,技术在于分享而进步