ESP32 BLE学习(0) — 基础架构

news2024/11/26 19:59:19

前言

(1)学习本文之前,需要先了解一下蓝牙的基本概念:BLE学习笔记(0.0) —— 基础概念(0)
(2) 学习一款芯片的蓝牙肯定需要先简单了解一下该芯片的体系结构,因此本文将会简单的介绍ESP32的蓝牙结构。
(3)因为乐鑫目前主推的是BLE低功耗蓝牙技术,因此我本人也主要侧重讲解BLE部分。

ESP32蓝牙系统介绍

蓝牙堆栈

(1)ESP-IDF 目前支持两个主机堆栈,Bluedroid默认) 和 Apache NimBLE

  • Bluedroid : 该堆栈支持传统蓝牙(BR/EDR)和低功耗蓝牙(BLE)。如果是传统蓝牙(BR/EDR)有需求,则必须使用该堆栈。
  • Apache NimBLE : 仅支持低功耗蓝牙。如果仅仅是对BLE有使用需求,建议选择该协议栈,因为该协议栈代码占用和运行时对内存的需求都会低一些。

蓝牙架构

(1)我们知道,蓝牙从整体架构上可以分为控制器 (Controller) 和主机 (Host) 。

  • 控制器 (Controller) : 通常是一个物理设备,它能够发送和接收无线电信号,并懂得如何将这些信号翻译成携带信息的数据包。主要用于硬件接口管理、链路管理等等。
  • 主机 (Host) : 它通常是一个软件协议栈,用于管理两台或多态设备间如何通讯以及如何实现无线电同时提供几种不同服务。它可以构建各种规范,向上层应用提供接口基础,方便应用层对蓝牙系统的访问编程。

(2)首先,我们需要知道为什么蓝牙需要分为控制器 (Controller) 和主机 (Host) 两层结构。这个时候我们就需要了解一下蓝牙技术设计初衷了,蓝牙致力于打造一种低成本的无线通讯方案,要实现低成本那么就需要有较大的销量。如今,手机作为当之无愧销量最大的消费电子设备,任何一项技术一旦进入了手机就非常容易取得成功。因此,低功耗蓝牙将会依附于蓝牙在手机上的高配售率快速拓宽市场
(3)既然你要依附手机,那么很多东西都要从手机厂的角度进行思考问题。那么,如果你仔细阅读蓝牙核心规格,你会发现规格书更多地是站在手机角度来阐述的,然后“顺带”描述一下手机周边蓝牙设备的实现原理。
(4)大家都知道,手机厂一般不只是做手机,还会做一些手机相关的周边设备,例如华为不仅仅做华为手机,还有华为平板,华为耳机,华为电脑等等。华为手机和华为电脑只要通过无线网络连接在一起,就能够无感控制对方并且传输数据。但是,如果华为手机和苹果电脑组合在一起,却做不到无感控制对方。这是为什么呢?
(5)因为,手机厂都会在自家设备上跑一套协议栈用于适配自家的电子产品。协议栈设计的越好,手机厂自家的各种设备间信息传输更稳定,安全,用户体验也越好。因此手机厂不会把自家的协议栈分享给别人一起使用,这也导致的华为手机苹果电脑之间部分功能无法实现的原因。(注意,虽然不同手机厂协议栈不一样,但还是符合SIG标准和规范的,因此大部分功能能够互通
(6)既然手机厂的协议栈是不进行公开的,那么就存在一个问题,如果手机厂好不容易将自家的协议栈部署在一颗蓝牙芯片上,突然发现又有一颗性能更好、更便宜的蓝牙芯片了,需要更换芯片怎么办?这个时候需要更换部署,对于手机厂来说成本太高。因此SIG将跑协议栈的Host层与硬件管理的Control层进行隔离,中间统一一个接口标准HCI层。这样的话,手机厂只需要在AP芯片上跑协议栈Host层,而负责硬件的Control层单独一个芯片。当需要更换蓝牙芯片的时候,直接换即可,因为都是统一的HCI接口。

在这里插入图片描述

(7)现在我们有了上述基础,再来看看ESP32的蓝牙结构。ESP32有一个Control层,负责物理层相关的处理。Host层就有三种应用场景:

  • 单芯片跑蓝牙程序:使用Control层和Host层都运行在ESP32上,Host层有三种选择,乐鑫官方提供的Bluedroid默认) 和 NimBLE 协议栈,或者自己在ESP32上编写一个自己的协议栈。
  • 双芯片跑蓝牙程序:在ESP32上运行Control层,外接一个运行蓝牙协议栈的Host层。
  • 认证测试:我们如果想要使用ESP32作为开发用的蓝牙芯片,那么就需要知道它是否符合一些认证标准。因此就可以使用一个UART外接PC机进行认证测试。

在这里插入图片描述

代码分析

(1)我们首先需要找到gatt_server_service_table例程根据上面所说的知识分析一下app_main()函数做了什么。
(2)该例程虽然是使用的Bluedroid协议栈,但是只用了BLE部分。
<1>esp_bt_controller_mem_release()因为我们这里只需要BLE部分,所以需要先将传统蓝牙的内存进行释放。

// 释放经典蓝牙控制器内存
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

<2>esp_bt_controller_init()是对Control层进行初始化,BT_CONTROLLER_INIT_CONFIG_DEFAULT()是一个宏作为蓝牙初始化的默认参数,这个宏默认仅初始化BLE部分

// 初始化蓝牙 Control 层 
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
    ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
    return;
}

<3>我们对蓝牙Control初始化完成之后,需要调用esp_bt_controller_enable()Control层进行使能。传入值是一个enum参数。

  • ESP_BT_MODE_IDLE : 失能蓝牙
  • ESP_BT_MODE_BLE : 仅运行低功耗蓝牙(BLE)
  • ESP_BT_MODE_CLASSIC_BT : 仅运行传统蓝牙(BR/EDR)
  • ESP_BT_MODE_IDLE : 即运行低功耗蓝牙(BLE)又运行传统蓝牙(BR/EDR)
// 使能蓝牙 Control 层
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
    ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
    return;
}

<4>如果我们的Host层不是运行在ESP32上,那么只需要进行如上操作即可。但是该例程是采用的单芯片方案,因此还需要对Host层进行初始化,这是使用的Bluedroid协议栈。

// 初始化蓝牙 HOST 层
ret = esp_bluedroid_init();
if (ret) {
    ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
    return;
}

<5>初始化bluedroid之后,再进行使能即可。

// 使能蓝牙 HOST 层
ret = esp_bluedroid_enable();
if (ret) {
    ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
    return;
}

<6>如下部分在后面章节会进一步讲解,各位看一下代码注释简单了解即可。

    // 注册 GATT 回调函数,处理所有的 GATT 事件
    ret = esp_ble_gatts_register_callback(gatts_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret);
        return;
    }

    // 注册 GAP 回调函数,
    ret = esp_ble_gap_register_callback(gap_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret);
        return;
    }

    /* 注册一个app_id, 协议栈将会分配一个对应的 gatts_if,用于标识一个 GATT 服务。
     * 调用这个函数就会触发 esp_ble_gatts_register_callback() 注册的回调函数中的 ESP_GATTS_REG_EVT 事件
     */
    ret = esp_ble_gatts_app_register(heart_rate_profile_tab[PROFILE_APP_IDX].app_id);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gatts app register error, error code = %x", ret);
        return;
    }

    // 设置本地 MTU 大小
    esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);
    if (local_mtu_ret){
        ESP_LOGE(GATTS_TABLE_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
    }

参考

(1)乐鑫官方文档:ESP32蓝牙架构
(2)《低功耗蓝牙开发权威指南》第三章 —— 低功耗蓝牙的体系结构。
(3)《低功耗蓝牙开发权威指南》2.9章节 —— 十亿只是小目标。
(4)博客园:三种蓝牙架构实现方案(蓝牙协议栈方案)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1825989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

模型 商业画布

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。九块拼图&#xff0c;构建商业模式。 1 商业画布的应用 1.1 商业画布用于明确“GreenCycle”初创企业&#xff08;虚构&#xff09;的商业模式 假设有一家名为“GreenCycle”的初创…

实拆一个风扇

fr:徐海涛(hunkxu)

湖南源点调查 知识产权侵权案中企业如何品牌保护与收集证据

湖南源点调查认为&#xff0c;要判断某产品是否侵犯了自己的知识产权&#xff0c;可以采取以下步骤&#xff1a; 明确自己的知识产权&#xff1a; 首先&#xff0c;确保你的知识产权&#xff08;如商标、专利、著作权等&#xff09;已经获得合法的注册或保护。 仔细研究你的…

IO流及字符集

IO流 作用&#xff1a; 用于读写文件中的数据 分类&#xff1a; 图来自黑马程序员网课 纯文本文件&#xff1a;Windows自带的记事本打开能读懂的文件&#xff0c;word excel不是纯文本文件 图来自黑马程序员网课 FileOutputStream: 操作本地文件的字节输出流&#xff0c;可…

工业 web4.0 的 UI 风格,独树一帜

工业 web4.0 的 UI 风格&#xff0c;独树一帜

Java—文件拷贝

将指定的文件或目录拷贝到指定目录夹下 import java.io.*; import java.util.Scanner;/*** 实现一个文件拷贝*/ public class FileCopy {public static void main(String[] args) {Scanner scanner new Scanner(System.in);System.out.println("请输入要拷贝的源文件路径…

抽象工厂模式(大话设计模式)C/C++版本

抽象工厂模式 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15927110.html #include <iostream> using namespace std;// 抽象产品Department ,定义具体产品的公共接口 class Department { public:virtual ~Department() default;virtual void Insert()…

next.js v14 升级全步骤|迁移 pages Router 到 App Router

【概括】本文升级整体按照官网文档指引进行&#xff0c;在迁移 pages Router 前先看了官网的实操视频。 【注意】文章内对 .babel.ts、next.config.js 进行了多次更改&#xff0c;最终配置可见 报错3: Server Error ReferenceError: React is not defined 一、升级 Next.js 版…

Boom 3D软件下载及安装教程

简介&#xff1a; Boom 3D是适用于Mac和Windows系统的专业音效增强软件&#xff0c;旨在通过播放器&#xff0c;媒体或流媒体服务等介质&#xff0c;在不同类型的耳机上以3D环绕效果播放媒体内容。您无需使用昂贵的耳机或其他附加环绕音效增强器即可感受3D环绕音乐。 安 装 包…

性能测试包括哪些方面?

性能测试、通过自动化测试工具模拟多种正常&#xff0c;峰值&#xff0c;以及异常的负载情况下对系统各项性能指标进行的测试。 负载测试、压力测试、容量测试都属于性能测试。 性能测试指标是衡量系统性能的评价标准 主要关注一些响应时间、并发用户/并发、点击率、吞吐量、…

助力知识博主,实现在家搞副业的FlowUs新策略

助力知识博主&#xff0c;实现在家副业的FlowUs新策略 我们设定了一个雄心勃勃的目标&#xff1a;帮助100位知识博主在FlowUs上实现副业成功。这个目标不仅得到了团队成员的广泛支持&#xff0c;甚至有人认为它过于保守&#xff0c;因为FlowUs的多功能性使其成为自媒体博主收入…

工资信息管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;津贴管理&#xff0c;管理员管理&#xff0c;绩效管理 用户账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告管理&#xff0c;津…

CCAA质量管理【学习笔记】​​ 备考知识点笔记(五)质量设计方法与工具

第五节 质量设计方法与工具 1 任 务 分 解 法 1.1 概念 任务分解法&#xff0c;又称工作分解结构 (Work Breakdown Structure, 简 称 WBS) 。WBS 指以可交付成果为 导向&#xff0c;对项目团队为实现项目目标并完成规定的可交付成果而执行的工作所进行的层次分解。W…

057、PyCharm 运行代码报错:Error Please select a valid Python interpreter

当我们在PyCharm运行代码时&#xff0c;提示如下图错误&#xff1a; 那么问题通常是由于PyCharm未正确配置Python解释器引起的。 我们只需按以下步骤重新配置Python解释器即可&#xff1a; 打开PyCharm设置&#xff1a; 在菜单栏中的点击 “File” -> “Settings”&#xf…

【Spine学习09】之导入皮肤两种方式[skin]

第一种&#xff1a;明确项目中某个角色是有两套皮肤的情况下 直接导入两套皮肤 1、添加SKIN皮肤指令 2、在ps中-文件-脚本-浏览【打开选中jsx脚本】 3、打开Spine 点击左上角&#xff0c;选择导入数据 就可以看到该角色的两套皮肤啦&#xff01; 第二种&#xff1a;刚开始角…

Android开发更改JDK版本

今天在跑GitHub上面一个Android项目时&#xff0c;在Android编译时出现如下错误&#xff1a; Unsupported Java. Your build is currently configured to use Java 17.0.2 and Gradle 7.0.2.错误原因&#xff1a; JDK和Gradle版本对应出错。 本地的JDK为1.8正好可以更改为本…

商品搬家到抖店

使用的工具为 张飞搬家&#xff0c;登录上去 张飞搬家 1 复制商品的网址 商品链接复制过去后&#xff0c;点击下面的开始批量复制 2 检查修改商品信息 价格啊、图片啊、各种商品属性啊&#xff0c;检查下&#xff0c;不合适的修改和补充 3 开始搬家 4 查看商品 打开抖店后…

配置完eslint没有用?

当你使用 npx eslint --init 生成配置文件后 你也配置好了.prettierrc 当你在代码写一点小问题的时候 发现eslint没有进行检查 原因是你生成的 .eslintrc.js中没有加上这个配置 extends: [.....plugin:prettier/recommended],加上以后重启vscode你会发现

用AI造谣每天收入1万元,最后只拘留5日?

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 当时我就震惊了!800多个MCN的自媒体账号每天收入1万元&#xff0c;最后拘留5日?难怪群里这么多人在晒收益截图&#xff0c;原来都是这样来的。 央视刚刚曝光一家MCN机构用AI造谣的事件&#xff0c;该公司用AI一天…

Servlet接口实现

项目搭建 pom文件引入依赖与打包配置。 <dependencies><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId>…