BLE 蓝牙广播包结构分享

广播报文和扫描报文解析

关于广播和扫描报文的解析如果想从协议本身就了解可以从头看起,如果想直接看看芯片的开发怎么使用,可以直接从第2节,报文解析开始。

 

图1  BLE报文结构

1.1 前导

前导是一个8比特的交替序列。根据接入地址的第一个比特为0或者1,分01010101和10101010两种。接收机可以根据前导的无线信号强度来配置自动增益控制。

1.2 接入地址

  接入地址有两种类型:广播接入地址和数据接入地址。

  • 广播接入地址:固定为0x8E89BED6,在广播、扫描、发起连接时使用。
  • 数据接入地址:随机值,不同的连接有不同的值。在连接建立之后的两个设备间使用。

 

1.3 报头

1.3.1 广播报文报头

 

 

 

 

 图2  广播报文报头                      图3  Advertising channel PDU Headercore_v4.2 page 2583

1)广播报文类型

 

图3  广播报文类型  

  2) 发送地址类型和接收地址类型

  发送地址类型和接收地址类型指示了设备使用公共地址(Public Address)还是随机地址(Random Address)。公共地址和随机地址的长度一样,都包含6个字节共48位。BLE设备至少要拥有这两种地址类型中的一种,当然也可以同时拥有这两种地址类型。

  • 公共地址(Public Address)

  公共地址由两部分组成,如下图。公共地址由制造商从IEEE申请,由IEEE注册机构为该制造商分配的机构唯一标识符OUI(Organizationally Unique Identifier)。这个地址是独一无二,不能修改的。Core_v4.2 P2576的1.3.1节描述了公共地址。

 

图4  公共地址结构

  • 随机地址

随机地址有包含两种:静态地址(Static Device Address)和私有地址(PrivateDevice Address)。Core_v4.2 P2577的1.3.2.1节描述了静态地址。

随机地址有包含两种:静态地址(Static Device Address)和私有地址(PrivateDevice Address)。Core_v4.2 P2577的1.3.2.1节描述了静态地址。

静态地址有如下要求:

a)       静态地址的最高2位有效位必须是1。

b)       静态地址最高2位有效位之外的其余部分不能全为0和1。

在私有地址的定义当中,又包含了两个子类:不可解析私有地址(Non-resolvable Private Address)和可解析私有地址(Resolvable Private Address,RPA)。CH57x使用的是静态地址,芯片在出厂时自带全球唯一的48位MAC地址。在提供的driver代码中,有获取MAC的接口,可以直接调用。

 

 

图5  CH57x 获取芯片MAC接口函数

1.4 长度

广播报文:长度域包含6个比特,有效值的范围是6~37。

数据报文:长度域包含5个比特,有效值的范围是0~31。

广播报文和和数据报文的长度域有所不同,主要原因是:广播报文除了最多31个字节的数据之外,还必须要包含6个字节的广播设备地址。6+31=37,所以需要6比特的长度域。

再次强调:广播时必须要包含6个字节的广播设备地址。

1.5 数据(AdvData)

广播和扫面响应的数据格式如下图所示,由有效数据部分和无效数据部分组成。 

 

图6广播和扫描响应的数据格式

1)  有效数据部分:包含N个AD Structure,每个AD Structure由Length,AD Type和AD Data组成。其中:

Length:AD Type和AD Data的长度。

AD Type:指示AD Data数据的含义。

AD Type的意义可以通过下面2种方式查看AD Type和他们表示的意义。

从官网查询,但是需要是会员才可以查询。

  https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm

查看WCH的SDK中的定义,AD type的定义在程序的“CH57xBLE_LIB.h”头文件中。定义如下:

// GAP_ADTYPE_DEFINES GAP Advertisement Data Types

#define GAP_ADTYPE_FLAGS                         0x01 //!< Discovery Mode: @ref GAP_ADTYPE_FLAGS_MODES

#define GAP_ADTYPE_16BIT_MORE                   0x02 //!< Service: More 16-bit UUIDs available

#define GAP_ADTYPE_16BIT_COMPLETE               0x03 //!< Service: Complete list of 16-bit UUIDs

#define GAP_ADTYPE_32BIT_MORE                    0x04 //!< Service: More 32-bit UUIDs available

#define GAP_ADTYPE_32BIT_COMPLETE               0x05 //!< Service: Complete list of 32-bit UUIDs

#define GAP_ADTYPE_128BIT_MORE                   0x06 //!< Service: More 128-bit UUIDs available

#define GAP_ADTYPE_128BIT_COMPLETE              0x07 //!< Service: Complete list of 128-bit UUIDs

#define GAP_ADTYPE_LOCAL_NAME_SHORT             0x08 //!< Shortened local name

#define GAP_ADTYPE_LOCAL_NAME_COMPLETE          0x09 //!< Complete local name

#define GAP_ADTYPE_POWER_LEVEL                   0x0A //!< TX Power Level: 0xXX: -127 to +127 dBm

#define GAP_ADTYPE_OOB_CLASS_OF_DEVICE           0x0D //!< Simple Pairing OOB Tag: Class of device (3 octets)

#define GAP_ADTYPE_OOB_SIMPLE_PAIRING_HASHC     0x0E //!< Simple Pairing OOB Tag: Simple Pairing Hash C (16 octets)

#define GAP_ADTYPE_OOB_SIMPLE_PAIRING_RANDR     0x0F //!< Simple Pairing OOB Tag: Simple Pairing Randomizer R (16 octets)

#define GAP_ADTYPE_SM_TK                         0x10 //!< Security Manager TK Value

#define GAP_ADTYPE_SM_OOB_FLAG                  0x11 //!< Security Manager OOB Flags

#define GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE    0x12 //!< Min and Max values of the connection interval (2 octets Min, 2 octets Max) (0xFFFF indicates no conn interval min or max)

#define GAP_ADTYPE_SIGNED_DATA                  0x13 //!< Signed Data field

#define GAP_ADTYPE_SERVICES_LIST_16BIT         0x14 //!< Service Solicitation: list of 16-bit Service UUIDs

#define GAP_ADTYPE_SERVICES_LIST_128BIT        0x15 //!< Service Solicitation: list of 128-bit Service UUIDs

#define GAP_ADTYPE_SERVICE_DATA                  0x16 //!< Service Data - 16-bit UUID

#define GAP_ADTYPE_PUBLIC_TARGET_ADDR           0x17 //!< Public Target Address

#define GAP_ADTYPE_RANDOM_TARGET_ADDR           0x18 //!< Random Target Address

#define GAP_ADTYPE_APPEARANCE                     0x19 //!< Appearance

#define GAP_ADTYPE_ADV_INTERVAL                   0x1A //!< Advertising Interval

#define GAP_ADTYPE_LE_BD_ADDR                     0x1B //!< LE Bluetooth Device Address

#define GAP_ADTYPE_LE_ROLE                         0x1C //!< LE Role

#define GAP_ADTYPE_SIMPLE_PAIRING_HASHC_256     0x1D //!< Simple Pairing Hash C-256

#define GAP_ADTYPE_SIMPLE_PAIRING_RANDR_256     0x1E //!< Simple Pairing Randomizer R-256

#define GAP_ADTYPE_SERVICE_DATA_32BIT           0x20 //!< Service Data - 32-bit UUID

#define GAP_ADTYPE_SERVICE_DATA_128BIT          0x21 //!< Service Data - 128-bit UUID

#define GAP_ADTYPE_3D_INFO_DATA                  0x3D //!< 3D Information Data

#define GAP_ADTYPE_MANUFACTURER_SPECIFIC       0xFF //!< Manufacturer Specific Data: first 2 octets contain the Company Identifier Code followed by the additional manufacturer specific data

 

// GAP_ADTYPE_FLAGS_MODES GAP ADTYPE Flags Discovery Modes

#define GAP_ADTYPE_FLAGS_LIMITED                0x01 //!< Discovery Mode: LE Limited Discoverable Mode

#define GAP_ADTYPE_FLAGS_GENERAL                0x02 //!< Discovery Mode: LE General Discoverable Mode

#define GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED  0x04 //!< Discovery Mode: BR/EDR Not Supported

 

图7 广播类型定义

 1.6 校验 

BLE采用的是24位CRC校验。CRC对报头、长度和数据进行计算。24位CRC的生成多项式如下:

 

2.  广播包解析

通过上文的描述,我们对BLE广播包有了大致的了解,接下来我们用沁恒的BLE Analyzer捕获一个peripheral的广播包,通过对实际广播包的分析来理解BLE报文结构和广播。广播包捕获实验的硬件连接如下。

http://www.wch.cn/downloads/WCH_BLEAnalyzer_zip.html(包含安装软件和使用说明)

        

3. 实例解析

以EXAM\BLE\Peripheral为例,进行广播和扫描报文的解释

 3.1 代码部分

// GAP - SCAN RSP data (max size = 31 bytes)

static uint8 scanRspData[ ] =

{

  // complete name

  0x12,   // length of this data                                                        AD Structure

  GAP_ADTYPE_LOCAL_NAME_COMPLETE,                                                      len + GAP_ADTYPE + data

  'S', 'i', 'm', 'p', 'l','e',' ','P','e','r','i','p','h','e','r','a','l',  

  // connection interval range

  0x05,   // length of this data

  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,

  LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms                      AD Structure

  HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),                                   len + GAP_ADTYPE + data

  LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s

  HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),

  // Tx power level

  0x02,   // length of this data                                                        AD Structure              GAP_ADTYPE_POWER_LEVEL,                                                                len + GAP_ADTYPE + data

  0       // 0dBm

};

// GAP - Advertisement data (max size = 31 bytes, though this is best kept short to conserve power while advertising)

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                                                        AD Structure

  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 ),                                               AD Structure

  HI_UINT16( SIMPLEPROFILE_SERV_UUID )

};

准备好广播和扫描报文数据,使用时需要将这些信息通过RF发出去,具体在代码中实现方式如下,使用到的函数如下:

 

蓝牙初始化函数如下:

 

BLE分析仪抓包

从上图可以看到:

第一行广播包,间隔时间约(Time:+54394us)50ms

广播包数据

 

 

 

看看PDU(Packet data)报头*1B+长度*1B+MAC*6B+数据

数据部分与advertData定义相同,如果需要添加数据部分,需要按照AD Structure的构造去添加。

后面2行是主机向地址0x84C2E4030252发起扫描请求(SCAN_REQ),然后设备对于扫描请求的响应(SCAN_RSP).

响应数据如下:

 

 

 

看看PDU(Packet data)报头*1B+长度*1B +MAC*6B+数据。

数据部分与scanRspData相同,如果修改需要按照AD Structure的构造去改造,并且保证长度不超过31B。

其他的AD Structure不过多的讲,着重说一下UUID:
UUID定义:

 “GATT层”中定义的所有属性都有一个UUID值,UUID是全球唯一的128位的号码,它用来识别不同的特性。

128位的UUID相当长,设备间为了识别数据的类型需要发送长达16字节的数据。为了提高传输效率,蓝牙技术联盟(SIG)定义了一个称为“UUID基数”的128位通用唯一识别码,结合一个较短的16位数使用。二者仍然遵循通用唯一识别码的分配规则,只不过在设备间传输常用的UUID时,只发送较短的16位版本,接收方收到后补上蓝牙UUID基数即可。

蓝牙UUID基数如下:

00000000 – 0000 – 1000 – 8000 – 008059B34FB

如要发送的16位UUID为0x2A01,完整的128的UUID便是:

00002A01 – 0000 – 1000 – 8000 – 008059B34FB

低功耗蓝牙使用的那部分UUID被分为下列几组:

l          0x1800 ~ 0x26FF:用作服务类通用唯一识别码。

l          0x2700 ~ 0x27FF:用于标识计量单位。

l          0x2800 ~ 0x28FF:用于区分属性类型。

l          0x2900 ~ 0x29FF:用作特性描述。

l          0x2A00 ~ 0x7FFF:用于区分特性类型。

 

posted @ 2022-01-06 19:49  debugdabiaoge  阅读(14298)  评论(0编辑  收藏  举报