BLE协议栈 – 介绍

本文深入讲解BLE技术领域的核心——BLE协议栈,涵盖物理层、链路层、L2CAP、SMB、ATT、GATT及GAP等关键部分。通过解析《BLE权威指南》,结合网络资源,为读者提供全面且深入的理解。

在BLE技术领域里有三个方向:BLE APP,BLE固件和BLE协议栈。其中BLE协议栈是基础,BLE芯片内部提供的固件程序充当驱动,手机上的APP作为控制端。做APP开发无需要太多的专业背景,而做固件开发则需要深入理解协议栈。

BLE协议栈的 官方文档 可以自由下载阅读,该文档排版优良,颇具可读性。可是该文档仅有英文版,整个文档多达2000多页,这无疑增加了非英语读者的阅读困难。网上能够找到一些关于协议栈的简单介绍,比如这个页面,概述了协议栈各层的主要概念,适合通览一遍。

 

这些网络资源对于协议栈的细节大多点到为止,无以深入,于是我尝试结合自己的经验,挑重点介绍一下BLE协议栈的内容。成文过程主要参考《BLE权威指南》一书,也利用Google+Baidu做了大量搜索,借鉴了许多第三方博客和论坛的优质答案并保留了原始链接,尽可能将一些问题解释清楚。

 

BLE协议栈 – 物理层(Physical Layer)
BLE协议栈 – 链路层(Link Layer)
BLE协议栈 – HCI
BLE协议栈 – L2CAP
BLE协议栈 – SM
BLE协议栈 – ATT
BLE协议栈 – GATT
BLE协议栈 – GAP

 

[本文转自红旭论坛,看完之后获益良多,故联系大佬Wireless-tech转之。]

在 Arduino 环境中,ESP32 默认使用的是 **Bluedroid** 协议栈(由 Espressif 官方提供),但如果你希望获得更灵活的 BLE 控制能力(如访问 `getServer()`、`ble_gap_conn_rssi_get` 等底层 API),推荐切换到 **NimBLE** 协议栈。 > ✅ **NimBLE** 是一个轻量级、高性能的开源 BLE 协议栈,在低功耗和资源占用方面优于 Bluedroid,且提供了更丰富的 API。 --- ## ✅ 如何在 Arduino 中切换 ESP32 的 BLE 协议栈为 NimBLE? ### 方法一:使用第三方库 `NimBLE-Arduino`(推荐 ⭐) 这是最简单、最稳定的方式,适用于绝大多数用户。 --- ### 🛠 步骤 1:安装 NimBLE-Arduino 库 1. 打开 **Arduino IDE** 2. 进入菜单: > 工具 → 管理库... 3. 在搜索框中输入: ``` NimBLE-Arduino ``` 4. 找到由 `h2zero` 维护的库(作者名通常是 `Hieromon Ahn` 或 `h2zero`) 5. 点击 **安装** 📌 当前版本建议 ≥ v2.0.6(支持 ESP32-Sx/C3/C6 等新型号) --- ### 📦 替代方式:手动安装(Git 克隆) ```bash cd ~/Arduino/libraries git clone https://github.com/h2zero/NimBLE-Arduino.git ``` 然后重启 Arduino IDE。 --- ### 🧩 步骤 2:修改代码以使用 NimBLE 头文件 将原来的 Bluedroid 头文件: ```cpp #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLEClient.h> ``` 替换为 **NimBLE 版本**: ```cpp #include <NimBLEDevice.h> #include <NimBLEServer.h> #include <NimBLEUtils.h> #include <NimBLEClient.h> ``` ⚠️ 注意:不要同时包含两者,否则会冲突! --- ### ✅ 步骤 3:验证是否成功启用 NimBLE #### 示例代码:创建服务器并获取 `getServer()` ```cpp #include <NimBLEDevice.h> #include <NimBLEServer.h> bool deviceConnected = false; // 自定义 GAP 事件处理器 class MyGapEventHandler : public BLEGapEventHandler { void handleGapEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) { switch (event) { case ESP_GAP_BLE_READ_RSSI_EVT: Serial.printf("✅ 收到 RSSI: %d dBm\n", param->read_rssi.rssi); break; default: break; } } }; void setup() { Serial.begin(115200); delay(100); // 初始化 NimBLE NimBLEDevice::init("ESP32-NimBLE-Demo"); // ✅ 可以安全调用 getServer() NimBLEServer* pServer = BLEDevice::getServer(); if (pServer) { Serial.println("🎉 成功获取服务器实例!"); } // 设置 GAP 事件处理器 NimBLEDevice::getServer()->getGapServer()->setEventHandler(new MyGapEventHandler()); // 创建服务 BLEService* pService = pServer->createService(BLEUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")); pService->start(); // 开始广播 NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising(); pAdvertising->addServiceUUID(BLEUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")); pAdvertising->start(); Serial.println("等待连接..."); } void loop() { // 示例:每 5 秒读取一次当前连接设备的 RSSI static uint32_t lastRead = 0; if (millis() - lastRead > 5000) { NimBLEServer* pServer = NimBLEDevice::getServer(); if (pServer && pServer->getConnectedCount() > 0) { // 获取第一个连接句柄 auto connId = pServer->getPeerDevice().first->first; // 简化示例 int rc = ble_gap_conn_rssi_get(connId); // ✅ 可用! if (rc != 0) { Serial.printf("❌ 无法发起 RSSI 请求: %d\n", rc); } else { Serial.println("正在读取 RSSI..."); } } lastRead = millis(); } delay(100); } ``` 📌 关键优势: - ✅ 支持 `BLEDevice::getServer()` - ✅ 支持 `ble_gap_conn_rssi_get(conn_id)` - ✅ 更细粒度控制 GAP/GATT 行为 - ✅ 内存占用更低 --- ### 方法二:通过 `sdkconfig.defaults` 强制启用 NimBLE(高级用户) 如果你使用的是官方 ESP32 Arduino Core 并想全局启用 NimBLE 栈(而不是默认的 Bluedroid),可以通过配置文件实现。 #### 步骤: 1. 在你的 `.ino` 文件所在目录创建文件: ``` sdkconfig.defaults ``` 2. 添加以下内容: ```ini CONFIG_BT_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_BLUEDROID_ENABLED=n CONFIG_BT_CONTROLLER_MODE_LE=y CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3 ``` 3. 重新编译项目 > ⚠️ 注意:此方法仅适用于支持该配置的 Arduino Core 版本(v2.0.5+),并且必须确保没有其他库依赖 Bluedroid。 --- ## 🔍 如何确认当前使用的是 NimBLE? ### 方法 1:查看串口输出日志 NimBLE 启动时会有类似日志: ``` I NimBLE: Host reset I NimBLE: BLE Host Task Started ``` 而 Bluedroid 输出是: ``` I BT_BTC: BTC_TASK starting ``` ### 方法 2:检查是否能调用 `ble_gap_conn_rssi_get` ```cpp extern "C" int ble_gap_conn_rssi_get(uint16_t conn_handle); // 如果链接成功,则说明是 NimBLE ``` ### 方法 3:查看内存使用情况 NimBLE 比 Bluedroid 节省约 30–50KB RAM。 --- ## ❗ 常见问题与注意事项 | 问题 | 解决方案 | |------|----------| | 编译错误 `undefined reference to 'ble_gap...'` | 确保使用了 `NimBLE-Arduino` 库,不是原生 `BLEDevice` | | `getServer()` 仍报错 | 检查是否包含了 `<NimBLEDevice.h>` 而非 `<BLEDevice.h>` | | 多个 BLE 库冲突 | 删除重复库(如 `BLE`, `CurieBLE`) | | 不支持 ESP32-C3? | 使用最新版 NimBLE-Arduino(≥ v2.0.6) | --- ## ✅ 总结:切换到 NimBLE 的完整流程 | 步骤 | 操作 | |------|------| | 1 | 安装 `NimBLE-Arduino` 库 | | 2 | 替换头文件为 `#include <NimBLEDevice.h>` 等 | | 3 | 使用 `BLEDevice::getServer()` 获取服务器对象 | | 4 | 利用 `ble_gap_conn_rssi_get()` 获取 RSSI | | 5 | (可选)通过 `sdkconfig.defaults` 全局启用 NimBLE | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值