【BLE】CC2541之主机端获取广播包数据

一、简介

本篇以SimpleBLECentral工程为例,,介绍CC2541作为主机时是如何获取从机广播包数据的。

二、实验平台

协议栈版本:BLE-CC254x-1.3.2

编译软件:IAR 8.20.2

硬件平台:smart RF开发板

三、简介广播包

广播包是从机端发出的数据包。

注:本篇中的“广播包”包含“广播包数据”和“扫描应答数据”。

1、SimpleBLEPeripheral工程中的广播数据包格式如下:

// GAP – Advertisement data (max size = 31 bytes, though this is// best kept short to conserve power while advertisting)static uint8 advertData[] ={ // Flags; this sets the device to use limited discoverable // mode (advertises for 30 seconds at a time) instead of general // discoverable mode (advertises indefinitely) 0x02, // length of this data GAP_ADTYPE_FLAGS, DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, // service UUID, to notify central devices what services are included // in this peripheral 0x03, // length of this data GAP_ADTYPE_16BIT_MORE,// some of the UUID's, but not all LO_UINT16( SIMPLEPROFILE_SERV_UUID ), HI_UINT16( SIMPLEPROFILE_SERV_UUID ),};

2、SimpleBLEPeripheral工程中的扫描应答数据包格式如下:

// GAP – SCAN RSP data (max size = 31 bytes)static uint8 scanRspData[] ={ // complete name 0x14, // length of this data GAP_ADTYPE_LOCAL_NAME_COMPLETE, 0x53, // 'S' 0x69, // 'i' 0x6d, // 'm' 0x70, // 'p' 0x6c, // 'l' 0x65, // 'e' 0x42, // 'B' 0x4c, // 'L' 0x45, // 'E' 0x50, // 'P' 0x65, // 'e' 0x72, // 'r' 0x69, // 'i' 0x70, // 'p' 0x68, // 'h' 0x65, // 'e' 0x72, // 'r' 0x61, // 'a' 0x6c, // 'l' // connection interval range 0x05, // length of this data GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE, LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), // 100ms HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // 1s HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // Tx power level 0x02, // length of this data GAP_ADTYPE_POWER_LEVEL, 0// 0dBm};广播数据包和扫描应答数据包的数据格式,都是由多个“数据长度+数据类型+数据”组成。

因此,我们可以通过判断数据类型,来获取这个类型的数据。

四、代码修改(SimpleBLECentral.c)

1、定义一个获取广播数据段的函数Get_Adtype_Data

//******************************************************************************//name:Get_Adtype_Data//introduce:获取广播数据或扫描应答数据中adType对应的数据//input parameter:adType:数据类型//pData:广播包或扫描应答包//dataLen:广播包或扫描应答包的数据长度//output parameter:adTypeData_index:对应的adType类型数据的偏移值//adTypeData_len:对应的adType类型数据的长度//return:TRUE:找到adType类型的数据//FALSE:没找到adType类型的数据//******************************************************************************static bool Get_Adtype_Data( uint8 adType, uint8 *pData, uint8 dataLen, uint8 *adTypeData_index, uint8 *adTypeData_len){(void)adTypeData_index;//防止编译报错 (void)adTypeData_len;//防止编译报错uint8 adLen;//对应数据段的长度 uint8 *pCurrent;//当前位置的指针 uint8 *pEnd;//尾指针pEnd = pData + dataLen – 1; //指向包尾pCurrent = pData;//当前指针指向包头while ( pCurrent < pEnd )//判断当前指针是否还未到包尾 {adLen = *pCurrent++;//获取本段数据段的长度if ( adLen > 0 ){if ( adType == *pCurrent )//如果找到了adType{*adTypeData_index = (pCurrent + 1) – pData;//数据段在数据包中的偏移值*adTypeData_len = adLen – 1;//数据段长度return TRUE;//返回TRUE}else//没找到adType则指向下一个数据段{pCurrent += adLen;}} }return FALSE;//本数据串中没有找到adType}

该函数是我参考simpleBLEFindSvcUuid写出来的,通过这个函数可以找出某个类型的数据段位置。

2、声明函数Get_Adtype_Datastatic bool Get_Adtype_Data( uint8 adType, uint8 *pData, uint8 dataLen, uint8 *adTypeData_index, uint8 *adTypeData_len);

3、定义一个十六进制转字符串的函数Hex_To_Str

//************************************************** //name:Hex_To_Str //input:十六进制进制转字符串 //return:修改后的字符串 //************************************************** char* Hex_To_Str( uint8 *pHex ) {charhex[] = "0123456789ABCDEF";static char str[100];char*pStr = str;for ( uint8 i = 0; i < sizeof(pHex); i++ ){*pStr++ = hex[*pHex >> 4];*pStr++ = hex[*pHex++ & 0x0F];}return str; } 这里字符串大小我定了100个字节,也就是最多只能转50个十六进制。将就用吧。

4、声明函数Hex_To_Str

char *Hex_To_Str( uint8 *pHex );

5、使用举例一——获取广播数据

代码修改:

case GAP_DEVICE_INFO_EVENT:{// if filtering device discovery results based on service UUIDif ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE ){if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,pEvent->deviceInfo.pEvtData,pEvent->deviceInfo.dataLen ) ){simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );{//读广播包或扫描应答包的某个数据段uint8 adType = GAP_ADTYPE_FLAGS; //需要扫描的类型数据uint8 adTypeData_index = 0;//数据段在数据包中的偏移值uint8 adTypeData_len = 0;//数据段的长度bool status = FALSE;status = Get_Adtype_Data( adType,pEvent->deviceInfo.pEvtData,pEvent->deviceInfo.dataLen,&adTypeData_index,&adTypeData_len);if(status == TRUE){NPI_PrintString("GAP_ADTYPE_FLAGS:");NPI_WriteTransport((uint8 *)(Hex_To_Str(pEvent->deviceInfo.pEvtData + adTypeData_index)),adTypeData_len*2);NPI_PrintString("\r\n");NPI_PrintValue("size:", adTypeData_len, 10);NPI_PrintString("\r\n");}} /*{//读广播包或扫描应答包的某个数据段uint8 adType = GAP_ADTYPE_16BIT_MORE; //需要扫描的类型数据uint8 adTypeData_index = 0;//数据段在数据包中的偏移值uint8 adTypeData_len = 0;//数据段的长度bool status = FALSE;status = Get_Adtype_Data( adType,pEvent->deviceInfo.pEvtData,pEvent->deviceInfo.dataLen,&adTypeData_index,&adTypeData_len);if(status == TRUE){NPI_PrintString("GAP_ADTYPE_16BIT_MORE:");NPI_WriteTransport((uint8 *)(Hex_To_Str(pEvent->deviceInfo.pEvtData + adTypeData_index)),adTypeData_len*2);NPI_PrintString("\r\n");NPI_PrintValue("size:", adTypeData_len, 10);NPI_PrintString("\r\n");}} */}}}break;

在GAP_DEVICE_INFO_EVENT事件中会有广播数据包和扫描应答数据包进来,因此本段代码先判断了UUID来确认此数据包是“广播数据包”。

然后再通过Get_adType_Data去获取GAP_ADTYPE_FLAGS数据段的数据。

注:注释部分是获取GAP_ADTYPE_16BIT_MORE数据段的代码,由于串口同一时间打印太多会不好使,所以我分开来编译GAP_ADTYPE_FLAGS数据段和GAP_ADTYPE_16BIT_MORE数据段的代码。

实验结果:

1)GAP_ADTYPE_FLAGS数据段获取结果

2)GAP_ADTYPE_16BIT_MORE数据段获取结果

6、使用举例二——获取扫描应答数据包的设备名称段

代码修改:

对于沙漠中的旅行者,最可怕的不是眼前无尽的荒漠,而是心中没有绿洲。

【BLE】CC2541之主机端获取广播包数据

相关文章:

你感兴趣的文章:

标签云: