深入解析蓝牙ATT协议:属性表设计与UUID分类实战指南

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

1. 从零开始:理解蓝牙BLE通信的基石——ATT协议

如果你玩过智能手环、蓝牙耳机或者用手机连接过智能体重秤,那你其实已经和蓝牙低功耗(BLE)技术打过交道了。在这些设备“默默无闻”地交换数据背后,有一个核心的通信规则在起作用,它就是属性协议,也就是我们常说的 ATT

你可以把ATT想象成一个设备内部精心编排的“数据仓库”。这个仓库里存放的不是货物,而是一条条结构化的数据记录,我们称之为属性。每个属性都有自己唯一的“货架编号”(句柄Handle)、明确的“货物类型标签”(UUID)、实际的“货物内容”(值Value)以及一套“存取规定”(权限Permissions)。手机(作为客户端)想要读取手环的心率数据,或者给智能灯泡发送一个“开灯”指令,本质上就是向这个“仓库”发起一次查询或修改请求。ATT协议就是定义了客户端如何发现、读取、写入这些属性的“标准操作手册”。

为什么理解ATT如此重要?因为它是BLE设备间所有数据交互的底层基础。无论你是在TI的CC26xx系列芯片上开发,还是使用Nordic的nRF52系列,甚至是乐鑫的ESP32,你编写的每一个服务、每一个特征值,最终都会在设备的内存中组织成一张属性表。这张表就是BLE设备对外提供所有功能的“服务清单”。作为开发者,你的核心任务之一就是设计并维护好这张表。理解了ATT,你就掌握了BLE设备如何组织、暴露和交换数据的核心逻辑,后续的GATT、服务发现等概念都将迎刃而开。

2. 属性表(Attribute Table)的深度剖析与实战构建

属性表是BLE服务端(通常是你的嵌入式设备,如传感器、手环)数据结构的核心体现。它不是一个抽象概念,而是在内存中真实存在的一个数组或链表。每个条目就是一个属性,包含了四个关键部分。

2.1 属性四要素:句柄、类型、值与权限

我们来逐一拆解,并用一个实际的代码片段(以TI SimpleLink SDK风格为例)来说明:

1. 属性句柄 (Attribute Handle) 这是一个16位的无符号整数(0x0001 - 0xFFFF),可以理解为属性在表中的唯一地址或索引。客户端(如手机APP)所有后续的读写操作,都必须通过这个句柄来指定目标属性。系统在初始化属性表时,会自动按顺序分配句柄。例如,第一个服务的声明句柄可能是0x0001,它的第一个特征值声明句柄就是0x0002,依此类推。

2. 属性类型 (Attribute Type) 这就是UUID。它回答了“这个属性是什么”的问题。UUID可以是16位(短UUID)或128位(长UUID)。蓝牙技术联盟(SIG)定义了大量标准的16位UUID,用于表示通用的服务、特征值和描述符类型。比如,0x180D 代表“心率服务”,0x2A37 代表“心率测量特征值”。当你需要自定义私有功能时,就需要使用128位的UUID。

这里有个关键技巧:所有SIG定义的16位UUID,实际上都基于一个128位的“蓝牙基础UUID”:00000000-0000-1000-8000-00805F9B34FB。系统内部会将你的16位UUID(如0x2A37)嵌入到这个基础UUID的特定位置(替换第3、4字节),形成完整的128位UUID。这既保证了全球唯一性,又节省了空中传输的数据量。

3. 属性值 (Attribute Value) 这就是属性承载的实际数据,长度从0到512字节不等。它可以是设备名称字符串、传感器的读数、一个开关状态,甚至是另一个服务的引用。对于特征值(Characteristic)属性,其值就是用户真正要读写的数据。

4. 属性权限 (Attribute Permissions) 它定义了客户端可以对这个属性做什么,以及需要满足什么安全条件。主要分为几个层次:

  • 访问权限:只读、只写、可读可写。
  • 加密权限:通信是否需要加密。
  • 认证权限:是否需要配对(身份验证)。
  • 授权权限:配对后,是否需要用户进一步授权(信任设备)。

权限是服务端强制执行的安全策略。例如,一个门锁的“开锁”特征值,其权限可能设置为“可写、需认证、需授权”。这意味着,即使手机与门锁已配对(认证),也必须被标记为“可信设备”(授权),才能成功发送开锁指令。

2.2 动手构建一个属性表:以TI CC26xx SDK为例

理论说再多,不如一行代码。我们来看如何在TI的BLE-Stack SDK中定义一个简单的属性表。假设我们要创建一个自定义服务,包含一个可读的温度特征值和一个可写、可通知的LED控制特征值。

首先,我们需要定义一个属性数组。在TI的SDK中,这通常在gatt_uuid.cgatt_profile.c等文件中完成。下面是一个简化的示例结构:

// 自定义服务的UUID (128位,示例用)
#define MY_SERVICE_UUID 0xFFF0
#define TEMP_CHAR_UUID  0xFFF1
#define LED_CHAR_UUID   0xFFF2

// 属性表定义 (概念性代码,实际SDK使用更复杂的宏)
static gattAttribute_t myServiceAttrTbl[] = {
    // 主服务声明 (Primary Service Declaration)
    {
        .type = GATT_PRIMARY_SERVICE_UUID, // 类型: 0x2800
        .handle = 0x0010, // 句柄,由系统或开发者指定范围
        .uuid = MY_SERVICE_UUID, // 服务UUID
        .permissions = GATT_PERMIT_READ, // 只读
        .value = &myServiceUUID // 指向服务UUID值的指针
    },

    // 温度特征

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值