在一个 BLE开发项目中,我采用的是TI的CC2541蓝牙BLE SoC,为了防止主从设备连接断开时数据丢失,硬件上加了一个EEPROM,当蓝牙建立连接时,通过Notify发给主机,但当蓝牙连接断开时,采集的数据要存储到EEPROM中(I2C),要实现这一点,需要实时获取蓝牙的连接状态。
在TI的BLE协议栈中,periperal.h中有如下定义:
/**
* GAP Peripheral Role States.
*/
typedef enum
{
GAPROLE_INIT = 0, //!< Waiting to be started
GAPROLE_STARTED, //!< Started but not advertising
GAPROLE_ADVERTISING, //!< Currently Advertising
GAPROLE_WAITING, //!< Device is started but not advertising, is in waiting period before advertising again
GAPROLE_WAITING_AFTER_TIMEOUT, //!< Device just timed out from a connection but is not yet advertising, is in waiting period before advertising again
GAPROLE_CONNECTED, //!< In a connection
GAPROLE_CONNECTED_ADV, //!< In a connection + advertising
GAPROLE_ERROR //!< Error occurred - invalid state
} gaprole_States_t;
以上枚举了从设备的几种状态,那么如何实时的获取gaprole_States_t的当前状态呢?该文件中后面由给出了一个定义:
/**
* Callback structure - must be setup by the application and used when gapRoles_StartDevice() is called.
*/
typedef struct
{
gapRolesStateNotify_t pfnStateChange; //!< Whenever the device changes state
gapRolesRssiRead_t pfnRssiRead; //!< When a valid RSSI is read from controller
} gapRolesCBs_t;
这个结构体上面的注释写的很清楚,必须在application层进行设置并在gapRoles_StartDevice()调用后使用。这里pfnStateChange成员变量是一个回调函数指针,用来处理相应状态变化下的操作。所以抓住这一点,也就实时获取到了从设备的连接状态变化。那么接下来我们只要在Application层定义一个pfnStateChange的回调函数并用来初始化一个gapRolesCBs_t的结构体即可。
回调函数定义如下:(gLinkStatus是自定义的一个变量,用来表示连接状态)
static void peripheralStateNotificationCB( gaprole_States_t newState )
{
switch ( newState )
{
case GAPROLE_STARTED:
{
uint8 ownAddress[B_ADDR_LEN];
uint8 systemId[DEVINFO_SYSTEM_ID_LEN];
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
// use 6 bytes of device address for 8 bytes of system ID value
systemId[0] = ownAddress[0];
systemId[1] = ownAddress[1];
systemId[2] = ownAddress[2];
systemId[3] = ownAddress[3];
systemId[4] = ownAddress[4];
systemId[5] = ownAddress[5];
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
gLinkStatus=0;
}
break;
case GAPROLE_ADVERTISING:
gLinkStatus=0;
break;
case GAPROLE_CONNECTED:
gLinkStatus=1;
break;
case GAPROLE_CONNECTED_ADV:
gLinkStatus=0;
break;
case GAPROLE_WAITING:
gLinkStatus=0;
break;
case GAPROLE_WAITING_AFTER_TIMEOUT:
gLinkStatus=0;
break;
case GAPROLE_ERROR:
gLinkStatus=0;
break;
default:
break;
}
}
然后用该回调函数初始化一个gapRolesCBs_t的结构体:
// GAP Role Callbacks
static gapRolesCBs_t TemperatureSensor_PeripheralCBs =
{
peripheralStateNotificationCB, // Profile State Change Callbacks
NULL // When a valid RSSI is read from controller (not used by application)
};
这样,在gapRoles_StartDevice()调用后(在应用层的任务处理函数中调用),便可以通过自定义的gLinkStatus变量来实时获取当前的连接状态了。
欢迎大家扫描下方二维码关注我的个人微信公众号,一起交流学习,谢谢。