• esp32系列(5):esp32 蓝牙架构学习


    目录

    1 ESP32 蓝牙架构学习

    1.1 蓝牙

    • 蓝牙是一种短距通信系统。

    • 蓝牙系统分为两种不同的技术(ESP32都支持):

      • 经典蓝牙(Classic Bluetooth)
      • 蓝牙低功耗(Bluetooth Low Energy)
    • 整体结构: 在这里插入图片描述

      分为控制器(Controller)和主机(Host)两大部分。

      • 控制器
        • 组成:包括PHY、 Baseband、 Link Controller、 Link Manager、 Device Manager、 HCI 等模块
        • 功能:硬件接口管理、链路管理等。
      • 主机
        • 组成:包括了了 L2CAP、 SMP、 SDP、 ATT、 GATT、 GAP 以及各种规范
        • 功能:构建了了向应用层提供接口的基础,方便便应用层对蓝牙系统的访问。
        • 特征:可以与控制器在同一宿主或不同宿主。
    • 由于主机的特征,ESP32 有几种典型应用场景:

      • 1 宿主相同(ESP-IDF默认):控制器(ESP32 Bluetooth Controller)与主机(ESP32 BLUEDROID )。
      • 2 宿主不同:控制器(ESP32 Bluetooth Controller)与主机(PC/Phone/Pad )。
      • 3 宿主不同:与2类似,但是用于BQB(或其它认证)的控制器测试。

    1.1.1 HCI 接口选择

    Host与Bluetooth Controller连接的HCI(主机控制接口, Host Controller Interface), 在ESP32中只能同时使用以下IO接口中的一个:

    • UART
    • VHCI
    • SDIO

    在ESP-IDF中,可以在 menuconfig 中配置蓝牙的 HCI IO接口方式。

    1.1.2 蓝牙运行环境

    ESP-IDF 的默认运行环境为双核 FreeRTOS, ESP32 的蓝牙可按照功能分为多个任务(task)运行,不同任务的优先级也有不同,其中优先级最的为运控制器的任务。控制器任务对实时性要求高,在FreeRTOS系统中的优先级仅次于IPC任务(IPC任务用于CPU的进程间通信)。BLUEDROID(ESP-IDF默认的蓝牙主机)共包含4个任务:

    • BTC
    • BTU
    • HCI UPWARD
    • HCI DOWNWARD

    1.1.3 框架

    1.1.3.1 控制器

    ESP32 同时支持 Classic BT 和 BLE,蓝牙版本4.2 。集成了H4 协议、 HCI、 Link Manager、 Link Controller、 Device Manager、 HW Interface 等功能。这些功能以库的形式提供给开发者。
    在这里插入图片描述

    1.1.3.2 BLUEDROID

    BLUEDROID蓝牙主机内部分为两层:

    • BTU层
      • 功能:负责蓝主机底层协议栈的处理,包括 L2CAP、 GATT/ATT、 SMP、 GAP 以及部分规范等。
    • BTC层(除去HCI)
      • 功能:负责向应用层提供接口支持、处理基于 GATT 的规范、处理杂项等 。

    所有的API都在ESP_API层,开发者应当使用“esp”为前缀的蓝牙API。

    1.2 经典蓝牙

    ESP-IDF 中的蓝主机协议栈源于 BLUEDROID,后经过改良以配合嵌入式系统的应。
    在底层中,蓝牙主机协议栈通过虚拟 HCI 接,与蓝牙双模控制进行通信;
    在上层中,蓝牙主机协议栈将为用户应用程序提供用于协议栈管理和规范的 API。

    主机协议栈支持的经典蓝牙协议和规范:

    • 规范: GAP、A2DP (SNK)、AVRCP (CT)
    • 协议: L2CAP、SDP、AVDTP、AVCTP

    协议模型:

    在这里插入图片描述

    • L2CAP:L2CAP,Logical Link Control and Adaptation Protocol,即逻辑链路控制和适配协议。
    • SDP:Service Discovery Protocol,服务发现协议
      • 功能:允许应用程序发现其他对等蓝牙设备提供的服务,并确定可用服务的特征。
    • GAP:Generic Access Profile,通用访问规范
      • 功能:提供有关设备可发现性、可连接性和安全性的模式和过程描述。
    • A2DP(Advanced Audio Distribution Profile,高级音频分发规范) 和 AVRCP(Audio/Video Remote Control Profile,音频/视频远程控制规范)
      • 实现高质量单声道或立体声音频内容传输的协议和过程。
    • SPP (Serial Port Profile,串口协议)
      • 能在蓝牙设备之间创建串口进行数据传输的一种设备。

    1.2.1 代码实现

    有关经典蓝牙的例程路径为:examplesluetoothluedroidclassic_bt。
    参考 bt_spp_acceptor demo,作为 acceptor 通过 spp 协议进行串口环回通信。
    调用api的流程为:

    • 1 esp_bt_controller_mem_release
      功能:按模式释放controller内存
      注意:esp_bt_controller_mem_release() 只能在esp_bt_controller_init() 之前或者 esp_bt_controller_deinit() 之后调用。
      初始化时调用了esp_bt_controller_mem_release()之后,使用esp_bt_controller_enable()来使用BLE才是安全的。
    • 2 esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
      功能:获得控制器配置选项。通过配置掩码启用了某些功能的一些选项或参数。
    • 3 esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
      功能: 初始化 BT controller 以分配 task 和其他 资源。
      注意:这个函数需要在调用任何 BT 函数之前调用一次。
    • 4 esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode);
      功能:使能 BT controller
      注意:调用之后不能再次调用。如果需要动态改变 controller 的模式,则需要调用 esp_bt_controller_disable() 之后重新调用此函数。
    • 5 esp_err_t esp_bluedroid_init(void);
      功能:初始化和分配蓝牙资源
      注意:必须优先于每一个bluetooth stuff。
    • 6 esp_err_t esp_bluedroid_enable(void);
      功能:启用蓝牙。
      注意:必须在esp_bluedroid_init()之后。
    • 7 esp_err_t esp_bt_gap_register_callback(esp_bt_gap_cb_t callback);
      功能:注册gap回调函数
      注意:此函数应在 esp_bluedroid_enable() 成功完成后调用
      回调函数中对 BT GAP 回调事件进行判断并处理,如果收到认证完成事件(ESP_BT_GAP_AUTH_CMPL_EVT),则输出认证成功的消息。如果收到传统配对的PIN请求的事件(ESP_BT_GAP_PIN_REQ_EVT),先判断PIN的位数,如果是16位则设置PIN为 0000 0000 0000 0000 ,如果是4位则设置PIN为 1234 。
    • 8 esp_err_t esp_spp_register_callback(esp_spp_cb_t callback);
      功能:注册spp模块初始化回调函数
    • 9 esp_err_t esp_spp_init(esp_spp_mode_t mode);
      功能:初始化 spp 模块
    • 10 esp_err_t esp_bt_gap_set_pin(esp_bt_pin_type_t pin_type, uint8_t pin_code_len, esp_bt_pin_code_t pin_code);
      功能:为传统配对(Legacy Pairing)设置默认参数。
      主文件代码:

    编译的过程如果报错:fatal error:esp_bt.h: no such file or directory
    在这里插入图片描述

    解决:需要在menuconfig工具中配置SPP环境,配置好的环境设置保存在工程路径下的 sdkconfig 文件中。

    在这里插入图片描述

    • 设置 component config -> Bluetooth 为打开
    • 设置 component config -> Bluetooth -> Bluetooth contriller -> Bluetooth contorller mode (BR/EDR/BLE/DUALMODE) 选择为 BR/EDR Only
    • 设置 component config -> Bluetooth -> Bluedroid Options 为 选中 Classic Bluetooth下的SPP协议。

    修改宏定义为显示数据:
    line 32: #define SPP_SHOW_MODE SPP_SHOW_DATA /*Choose show mode: show data or speed*/

    测试结果:

    在这里插入图片描述

    • 手机下载蓝牙串口调试助手软件,连接名为“SPP_ACCEPTOR_DEMO”的蓝牙设备
      监视器:W (3646) BT_APPL: new conn_srvc id:26, app_id:255

    • 手机发送数据“12345678”
      监视器:

      I (3646) SPP_ACCEPTOR_DEMO: ESP_SPP_SRV_OPEN_EVT
      I (10906) SPP_ACCEPTOR_DEMO: ESP_BT_GAP_MODE_CHG_EVT mode:2
      I (11706) SPP_ACCEPTOR_DEMO: ESP_BT_GAP_MODE_CHG_EVT mode:0
      I (11726) SPP_ACCEPTOR_DEMO: ESP_SPP_DATA_IND_EVT len=4 handle=129
      I (11726) : 12 34 56 78 
      
      • 1
      • 2
      • 3
      • 4
      • 5

    蓝牙串口通信测试完成。

    1.3 低功耗蓝牙

    1.3.1 GAP(Generic Access Profile)

    Generic Access Profile,通用访问规范。
    功能:定义了了 BLE 设备的发现流程,设备管理和设备连接的建立。

    BLE GAP采用API调用和事件(Event)返回的设计模式,通过事件返回来获取 API 在协议栈的处理结果。当对端设备主动发起请求时,也是通过事件返回获取对端设备的状态。

    BLE设备定义四类 GAP 角色:

    • 广播者(Broadcaster):处于这种角色的设备通过发送广播 (Advertising) 让接收者发现自己。这种角色只能发广播,不能被连接。
    • 观察者(Observer):处于这种角色的设备通过接收广播事件并发送扫描(scan)请求。这种角色只能发送扫描请求,不能被连接。
    • 外围设备(Peripheral): 当广播者接受了观察者发来的请求后就就会进入这种角色。当设备进入这种角色后,将会作为从设备(slave)在链路中进行通信。
    • 中央设备(Central): 当观察者主动进行初始化,并建立一个物理链路时就会进入这种角色。这种角色在链路中被称为主设备(master)

    1.3.1.1 BLE角色转换图

    在这里插入图片描述

    1.3.1.2 BLE广播流程

    方式:

    • 使用public地址进行广播
    • 使用可解析地址进行广播
    • 使用静态随机地址进行广播

    类型:

    • 可连接可扫描非定向广播 (Connectable scannable undirected event type)
    • 高占空比定向广播 (High duty cycle directed event type)
    • 可扫描非定向广播 (Scannable undirected event type)
    • 不可连接非定向广播 (Non-connectable undirected event type)
    • 可连接低占空比定向广播 (Connectable low duty cycle directed event type)

    1.3.1.3 BLE扫描流程

    在 ESP32 中,扫描设备主要是通过调用 esp_ble_gap_set_scan_params 来设置扫描时的参数,然后调用 esp_ble_gap_start_scanning 开始扫描。扫描到的设备将会通过ESP_GAP_BLE_SCAN_RESULT_EVT 事件返回,最后当 duration 超时,会通过ESP_GAP_SEARCH_INQ_CMPL_EVT 事件返回。

    1.3.2 GATT(Generic Attribute Profile)

    1.3.2.1 ATT(Attribute Protocol)

    BLE 中的数据以属性(Attribute)方式存在,每条属性由四个元素组成:

    • 属性句句柄 (Attribute Handle) :类似于地址。
    • 属性类型 (Attribute UUID) : 每个数据有自己需要代表的意思,用标识码 (UUID)区分。
    • 属性值 (Attribute Value):属性值是每个属性真正要承载的信息。
    • 属性许可 (Attribute Permissions) :每个属性对各自的属性值有相应的访问限制。

    在这里插入图片描述

    服务器(server): 存有数据(即属性)的设备。
    客户端(client): 获取别人设备数据的设备。

    常用操作:

    • 客户端给服务端发数据:通过 写入请求 (Write Request)需要对方回复响应(Write Response)。写入命令 (Write
      Command)不需要。
    • 服务端给客户端发数据:通过 服务端指示 (Indication) 、通知 (Notification)
    • 客户端也可以主动通过读操作读取服务端的数据

    服务和客户端之间的交互操作都是通过上述的消息 ATT PDU 实现的。每个设备可以指定自己设备支持的最大 ATT 消息长度,我们称之为 MTU。 ESP32 IDF 里面规定 MTU 可以设置的范围是 23~517 字节,对属性值的总长度没有做限制。

    1.3.2.2 GTAA 规范

    ATT 属性协议规定了在 BLE 中的最小数据存储单位,而 GATT 规范则定义了:

    • 如何用特性值和描述符表示一个数据
    • 如何把相似的数据聚合成服务 (Service)
    • 以及如何发现对端设备拥有哪些服务和数据
    • GATT 规范引进了了特性值的概念,增加数据额外的信息。

    为了包含额外的这些信息,每个属性中均需要安排一大段数据空间,存储这些额外信息。然而,一个数据很有可能用不不到绝大部分的额外信息,因此这种设计并这不符合 BLE “协议尽可能精简”的要求。在此背景下, GATT 规范引进了描述符的概念,每种描述符可以表达一种意思,用户可使用描述符,描述数据的额外信息。必需说明的是,每个数据和描述符并非一一对应,即一个复杂的数据可以拥有多个描述符,而一个简单的数据可以没有任何描述符。

    BLE 协议中会把一些常用的功能定义成一个个的服务 (Service)*,每个服务包含若干个特性,每个特性包含若干个描述符。

    在这里插入图片描述

    1.3.2.3 基于 ESP32 IDF 建立 GATT 服务(GATT 服务)

    通过属性表 (Attribute Table)* 添加服务和特性的功能。用户只需将要添加的服务和特性逐一填入一个表格,然后调用
    esp_ble_gatts_create_attr_tab 函数,即可添加对应的服务和特性。

    1.3.2.4 基于 ESP32 IDF 发现对方设备的服务信息(GATT 客户端)

    • 首先发现对方所有的 Service 信息,包括 Service 的 UUID 和 Handle 范围。
    • 然后在 GATT 的 Handle 范围内 ,继续查找所有的特性。
    • 然后在 GATT 的 Handle 范围内 ,继续查找特性后的所有的描述符。

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    nginx学习使用
    STM32——SD卡实验(SDIO方式)
    W5500+树莓派RP2040入门教程之MQTT篇(十二)
    Jenkins教程—构建多分支流水线项目
    LLM-TAP随笔——语言模型训练数据【深度学习】【PyTorch】【LLM】
    苹果电脑Mac系统运行速度又卡又慢是怎么回事?
    微服务项目(maven父子级项目)怎么打包
    YOLOv7训练自己的数据集(口罩检测)
    【工具】压力测试、安全、进程、流量、磁盘、日志
    可执行文件的装载与进程
  • 原文地址:https://blog.csdn.net/m0_67393686/article/details/126082958