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.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开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

猜你喜欢

转载自blog.csdn.net/m0_54864585/article/details/126056595