BLE系列之一:GATT服务与数据收发
本文介绍了BLE(低功耗蓝牙)的GATT通信基础与常见问题。GATT是蓝牙设备间数据通信的统一规则,采用层级结构:服务(功能单元)→特征值(数据通道)→描述符(属性配置)。通信核心包括广播、连接、服务发现和数据收发(读/写/通知)。文章重点解析了Notify推送和Write写入的完整流程,并总结了三大常见问题:收不到数据(未配置CCCD描述符最常见)、搜不到设备(广播问题)和连接失败(参数不匹配等
·
BLE系列文章及实际踩坑经验,第一篇主要是BLE入门:GATT服务与数据收发。欢迎大家在评论区交流看法、提出疑问或分享实践心得,一起探讨。
低功耗蓝牙 BLE 是嵌入式 IoT 最常用无线方案,本文从 GATT 核心概念讲起,完成一次完整通信。
一、先搞懂:GATT 到底是什么?
GATT:蓝牙设备之间数据通信的统一规则
1. 层级关系(从上到下)
GATT
└── 服务(Service)
└── 特征值(Characteristic)
└── 描述符(Descriptor)
- Service(服务):功能单元(如电池服务、串口服务、心率服务)
- Characteristic(特征值):真正用于 读 / 写 / 通知 / 指示 的数据通道
- Descriptor(描述符):配置通道属性,最关键:CCCD 0x2902(开关 Notify)
2. 关键角色
- Server(从机 / 外设):发广播、存数据、提供服务(如 ESP32)
- Client(主机 / 中心设备):扫描、连接、读写数据(如手机)
3. 最常用权限(决定能不能通信)
- Read / Write / Write Without Response
- Notify(无应答推送)
- Indicate(带应答推送,更可靠)
- Broadcast / Signed Write
4. 理解成一个文件结构
你可以把它理解成:一个文件目录结构手机(客户端)访问设备(服务端)的文件。
GATT 固定结构
设备 (Server)
└── 服务 (Service) → 一个功能模块(UUID)
└── 特征值 (Characteristic) → 真正收发数据的地方
├── 读 Read
├── 写 Write
├── 通知 Notify (设备主动发数据给手机)
└── 描述符 (Descriptor 0x2902) → 开关通知
通俗理解
- Service = 文件夹
- Characteristic = 文件
- Notify = 设备主动把文件推给手机
- Write = 手机往文件里写数据
二、BLE 通信最核心的 4 件事
- 广播 → 让手机能搜到设备
- 连接 → 手机与设备建立通信链路
- 发现服务 → 手机找到服务与特征值
- 收发数据 → 读、写、通知、指示
三、数据收发完整流程(最关键)
设备 → 手机(Notify 主动推送)
- 设备启动广播
- 手机扫描并连接
- 手机打开 0x2902 描述符(通知开关)
- 设备调用 Notify 发送数据
- 手机成功接收
手机 → 设备(Write 写入)
- 手机连接设备
- 找到对应特征值
- 手机直接执行写操作
- 设备收到数据并触发回调
四、最容易踩的 3 个巨坑(99% 人中招)
坑 1:收不到数据
- 未写 CCCD 0x2902(最常见)
- 特征值未开启 Notify/Indicate 属性
- 从机未调用发送函数
- MTU 不匹配导致分包失败
- 数据发送过快,队列溢出
- 连接已断开但上层无感知
- 主机未注册数据接收回调
- 加密未完成就开始收发
- 从机程序崩溃、死机
坑 2:搜不到设备
- 广播未启动 / 设备未上电
- 广播间隔过大,手机扫描不到
- 扫描过滤条件错误(名称 / UUID 不匹配)
- 设备已被连接,连接后默认停止广播
- 硬件 PA 关闭、天线异常
- 手机蓝牙缓存异常
- 距离过远、遮挡严重
- 从机进入睡眠,广播暂停
- 手机未开启定位 / 蓝牙权限
坑 3:配对不上 / 连接失败 / 连接秒断
- 设备已被其他主机连接
- 安全参数不匹配(主机要求加密,从机不支持)
- 绑定信息冲突(清除配对后重试)
- 连接参数设置极端,导致协议栈崩溃
- 内存溢出、栈溢出、看门狗复位
- 供电不足(连接瞬间电流大导致掉电)
- 配对方式不支持(如从机仅 Just Works,主机强制密码)
- 服务发现过程中被中断
更多推荐



所有评论(0)