【Ble】(15)ble入门
2026/6/23 19:10:50 网站建设 项目流程

一、几个基本角色概念

两个角色(GAP 层定义)

  • Peripheral(外设/从机)= 你的戒指:发广播、被连接、提供数据。资源少、省电。
  • Central(中心/主机)= 手机:扫描、发起连接、主动读写。

两个核心框架

  • GAP(Generic Access Profile):管"怎么被发现、怎么连接"——广播、扫描、连接、断开。你日志里的[GAP ROLE N]就是它的状态机。
  • GATT(Generic Attribute Profile):管"连上之后怎么交换数据"——服务、特征、读/写/通知。A5C3/A5C4/A5C5 就是 GATT 的东西。

协议栈分层(从下到上,理解即可):

PHY(2.4GHz 物理射频,1M/2M 调制) └ LL 链路层(广播、连接、跳频、CRC、重传)——跑在芯片 ROM 里 └ L2CAP(通道复用、分包重组) └ ATT(属性协议:读/写一个个"属性") └ GATT(把属性组织成 服务/特征) └ SMP(配对加密,你现在没用) GAP(横跨:广播/连接策略 + 设备名)

你写命令是在最上面 GATT/ATT 层,但底下 LL/PHY 一直在默默跳频、重传、维持连接。


二、完整流程(对应你的日志)

阶段 0:上电初始化

SDK Version ID … / rfClk … / [ble-ring] service registered (8 attrs) ======================SimpleBLEPeripheral_Init Done==================== [ble-mac] static C2:09:4D:FC:B7:40 cfg=0 [GAP ROLE 1]
  • 协议栈初始化、把 GATT 属性表(服务/特征)登记进去(service registered 8 attrs)。
  • 设好设备地址(那个出厂唯一 MAC)。
  • [GAP ROLE 1]=GAPROLE_STARTED:栈起来了,但还没开始广播

阶段 1:广播(Advertising)

[GAP ROLE 2] = GAPROLE_ADVERTISING

设备周期性3 个广播信道(37/38/39,频率 2402/2426/2480 MHz——特意避开 WiFi)上发广播包。

  • 广播间隔:每隔几十~几百毫秒发一轮(可配)。间隔越短越好被发现,但越费电。
  • 广播包内容:设备名(BS-Ring2)、Flags、有时带厂商数据。手机扫描看到的名字/地址就来自这里。
  • 这是单向广撒,谁都能收,还没有"连接"。

阶段 2:扫描与发现(手机侧)

手机在同样 3 个信道上监听(扫描)。听到你的广播包 → 显示在列表里(名字 + 地址 + 信号强度 RSSI)。

  • 手机可选发一个Scan Request问"还有更多信息吗?",设备回Scan Response(我们把地址尾段塞这里)。
  • 这一步只是"看见",还没连。

阶段 3:建立连接(Connection)

你在手机点"连接" → 手机(此刻变成发起方)发一个CONNECT_IND(连接请求)包,里面包含一整套连接参数:

  • 接入地址(Access Address):这条连接的唯一标识。
  • 连接间隔(Connection Interval):每隔多久双方"碰一次头"(7.5ms~4s)。
  • 从机延迟(Slave Latency):从机可以跳过几次碰头不回(省电)。
  • 监督超时(Supervision Timeout):多久收不到对方就判定"断了"。
  • 跳频参数(信道图 + hop):之后在37 个数据信道自适应跳频通信(抗干扰)。

设备收到 → 进入连接态:

[GAP ROLE 5] = GAPROLE_CONNECTED

从这一刻起,双方在每个"连接事件(Connection Event)"按约定的连接间隔在跳频信道上短暂收发,平时射频关掉省电。这就是 BLE 省电的关键——不是一直开着,是"约好时间见面"。

阶段 4:连接参数协商(你日志里这条)

[2Mbps | DLE | MTU 247]

连上后双方会协商把"管道"加粗加快:

  • 2Mbps PHY:物理层从 1M 提到 2M,传输更快。
  • DLE(Data Length Extension):链路层单包数据从 27 字节扩到最多 251 字节。
  • MTU 247:ATT 层单次能传的最大字节数从默认 23 提到 247。

→ 意义:一次能塞更多数据、更快。你的命令帧最长 254 字节,MTU 247 基本一次一帧搞定(再大就要分包)。

阶段 5:GATT 服务发现(上一条消息讲过)

手机问"你有哪些服务/特征?",设备把整张 ATT 表回出去 → 手机解析出 A5C3 服务、A5C4(可写)、A5C5(读+通知)及各自句柄。这是 app 不用预先知道 UUID 就能操作的原因。

阶段 6:数据交换(你正在做的)

连上 + 发现完,才真正收发业务数据:

  • 写(Write):手机往A5C4写命令帧 → 设备[ble-ring] rx 14 B→ 解析 → handler。
  • 通知(Notify):设备要主动推数据,手机必须先订阅——往 A5C5 的CCCD(0x2902)01 00(就是你点"启用通知"做的)。订阅后设备GATT_Notification把回包推到 A5C5 → 手机收到。
    • 这就是为什么没订阅时回包被丢(我们之前-> -1的坑)。
  • (还有Read/Indicate等方式,你这套用的是 Write + Notify。)

阶段 7:连接维持与断开

  • 连接期间,即使没数据,双方也按连接间隔定期碰头(空包)以维持链路;超过监督超时没碰上头 → 判定断开。
  • 断开(对方主动断 / 超时 / 距离远信号丢):
[GAP ROLE 4] = GAPROLE_WAITING_AFTER_TIMEOUT(刚断,等待期) [GAP ROLE 2] = 重新开始广播

断开时 CCCD 订阅会被清掉→ 重连后必须重新启用通知(你之前重连后第一次-> -1就是这个)。


三、把你设备的 GAP ROLE 状态串起来

[GAP ROLE 1] STARTED 栈就绪,未广播 ↓ [GAP ROLE 2] ADVERTISING 广播中(手机能扫到) ↓ 手机发起连接 [GAP ROLE 5] CONNECTED 已连接 → 协商(2M/DLE/MTU)→ 发现 → 收发数据 ↓ 断开/超时 [GAP ROLE 4] WAITING_AFTER_TIMEOUT 刚断 ↓ [GAP ROLE 2] ADVERTISING 回到广播,等下次连接

(还有 0=INIT、3=WAITING、6=CONNECTED_ADV、7=ERROR,你常见的是 1→2→5→4→2 这个循环。)


四、几个容易混淆的点(给新手)

概念一句话
广播 vs 连接广播=单向广撒谁都能收;连接=一对一私有管道,要先建立
GAP vs GATTGAP 管"连不连";GATT 管"连上后传什么数据"
MTU vs DLEMTU 是 ATT 层一次能传多少;DLE 是链路层单包多大。两层独立,都影响吞吐
Write vs NotifyWrite=手机推给设备(主动);Notify=设备推给手机(需先订阅 CCCD)
连接间隔 vs 广播间隔广播间隔=多久发一次广播;连接间隔=连上后多久碰一次头
配对/绑定(SMP)加密 + 记住对方。你现在没用(明文、每次重新发现),量产可能要加

五、你现在所处的位置 & 还没碰的部分

  • 已打通:广播 → 连接 → 服务发现 → Write 命令 → Notify 回包(电量查询验证过)。
  • 还没做/可选:
    • 配对加密(SMP):目前明文传输,谁连上都能读写。
    • 连接参数主动优化:从机可请求更省电的连接间隔/延迟(低功耗阶段会用到)。
    • 断连自动重连 / 白名单:只让绑定过的手机连。
    • 分包重组:超过一个 MTU 的大数据(历史记录、OTA)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询