赞
踩
本篇博文最后修改时间:2017年01月06日,11:06。
一、简介
本文以SimpleBLECentral工程为例,介绍CC2541作为主机时是如何获取从机广播包数据的。
注:本篇中的“广播包”包含“广播包数据”和“扫描应答数据”。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF(主芯片CC2541
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:897503845@qq.com
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
五、基础知识
1、广播包是什么?
答:广播包是从机端发出的数据包。
2、广播包的格式是如何的?
答:
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
- };
因此,我们可以通过判断数据类型,来获取这个类型的数据。
六、实验步骤
1、添加一个获取广播数据段的函数Get_Adtype_Data
1)定义一个获取广播数据段的函数Get_Adtype_Data(SimpleBLECentral.c中)
- //******************************************************************************
- //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写出来的,通过这个函数可以找出某个类型的数据段位置。
static bool Get_Adtype_Data( uint8 adType, uint8 *pData, uint8 dataLen, uint8 *adTypeData_index, uint8 *adTypeData_len);
2、定义一个十六进制转字符串的函数Hex_To_Str(SimpleBLECentral.c中)
- //**************************************************
- //name: Hex_To_Str
- //input: 十六进制进制转字符串
- //return: 修改后的字符串
- //**************************************************
- char* Hex_To_Str( uint8 *pHex )
- {
- char hex[] = "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个十六进制。将就用吧。
3、声明函数Hex_To_Str(SimpleBLECentral.c中)
char *Hex_To_Str( uint8 *pHex );
4、分别获取广播数据与扫描应答数据的举例
1)使用举例一——获取广播数据中的数据段
①代码修改(SimpleBLECentral.c中)
- case GAP_DEVICE_INFO_EVENT:
- {
- // if filtering device discovery results based on service UUID
- if ( 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数据段的代码。
②实验结果
其中,GAP_ADTYPE_FLAGS数据段获取结果
其中,GAP_ADTYPE_16BIT_MORE数据段获取结果
2)使用举例二——获取扫描应答数据包的设备名称段
①代码修改(SimpleBLECentral.c中)
- case GAP_DEVICE_INFO_EVENT:
- {
- {
- //读广播包或扫描应答包的某个数据段
- uint8 adType = GAP_ADTYPE_LOCAL_NAME_COMPLETE; //需要扫描的类型数据
- 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_PrintValue("GAP_ADTYPE_FLAGS:", *p_adTypedata, 10);
- NPI_PrintString("GAP_ADTYPE_LOCAL_NAME_COMPLETE:");
- 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");
- }
- }
串口输出结果不太好用,只输出了设备名的前两个字节“0x53(S)”和“0x69(i)”。
(群友指出上面只显示2个字节的原因是:16进制转字符串的函数中,“sizeof(pHex)”只是取指针大小,因为指针是2字节大小,所以只输出了2个字节)。
所以在仿真中直接查看设备名是否有被获取到:
对照下面这个设备名,可见设备名已经存在于pEvent->deviceInfo.pEvtData中了,并且首地址是“pEvent->deviceInfo.pEvtData + adTypeData_index”,长度是adTypeData_len的0x13个(19个)。
- 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'
因此,实验成功。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。