IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> BLE低功耗蓝牙协议栈 -> 正文阅读

[系统运维]BLE低功耗蓝牙协议栈

目录

一. BLE低功耗蓝牙协议栈

(1)蓝牙核心协议(Bluetooth Core)

(2)蓝牙应用层协议(Bluetooth Application)

(3)BLE低功耗蓝牙核心协议层详解(Bluetooth Core)

① 物理层(PHY)

② 链路层(LL)

③ 主机控制接口层(HCI)

④ 通用访问配置文件层(GAP)

⑤ 逻辑链路控制及自适应协议层(L2CAP)

⑥ 安全管理层(SM)

⑦ 属性协议层(ATT)

⑧ 通用属性配置文件层(GATT)

(4)ATT协议层中的属性(attribute)

(4.1)属性的组成(数据结构)

二. BLE中的GAP和GATT:

1. 引言:

2. GAP:

2.1 设备角色

2.2 广播数据

3. GATT

3.1 GATT通信事务

3.2 GATT结构

????????????????????????Profile

????????????????????????Service

????????????????????????Characteristic

????????????????????????UUID

三.?一些常见术语概念

1. ATT PDU(属性协议)

2. GAP Bond管理

使用GAPBondMgr

四. 如何通过无线发送一个数据包

广播方式

连接方式


经典蓝牙(BT):一般用于数据量比较大的传输,如:语音、音乐等较高数据量的传输。

低功耗蓝牙模块(BLE):最大的特点就是成本和功耗的降低,可应用于实时性要求较高的产品当中,比如:智能家居类(蓝牙锁、蓝牙灯)、传感设备的数据发送(血压计、温度传感器)、消费类电子(电子烟、遥控玩具)等。

BTBLE两者物理层调制解调方式是不一样的,所以BLE设备和BT设备两者之间是不能相互通信的,选型的时候千万不要搞混,如果主设备是BLE设备,从设备也必须是BLE设备;同样,BT的从设备也只能和BT的主设备进行通信。

不过市场上还有一种双模蓝牙设备,即同时支持BLE和BT,比如我们天天用到的手机,手机可以和BT设备通信,也可以和BLE设备通信,但这不代表BLE设备可以和BT设备通信。其实是手机使用了分时机制来达到同时和BLE设备以及BT设备通信的目的,即手机让双模蓝牙芯片不断地在BLE模式和BT模式之间进行切换,以同时支持BLE设备和BT设备。

一. BLE低功耗蓝牙协议栈

深入浅出讲解低功耗蓝牙(BLE)协议栈 - 知乎

BLE协议栈主要用来对你的应用数据进行层层封包,以生成一个满足BLE协议的空中数据包。也就是说,把应用数据包裹在一系列的帧头(header)和帧尾(tail)中。

蓝牙协议规定了两个层次的协议:

(1)蓝牙核心协议(Bluetooth Core)

蓝牙核心协议关注对蓝牙核心技术的描述和规范,它只提供基础的机制,并不关心如何使用这些机制。

蓝牙核心协议又包含BLE Controller和BLE Host两部分。

  • Controller:负责定义RF、Baseband等偏硬件的规范,并在这之上抽象出用于通信的逻辑链路(Logical Link);
  • Host:负责在逻辑链路的基础上,进行更为友好的封装,这样就可以屏蔽掉蓝牙技术的细节,让Bluetooth Application更为方便的使用。

(2)蓝牙应用层协议(Bluetooth Application)

蓝牙应用层协议,是在蓝牙核心协议的基础上,根据具体的应用需求,百花齐放,定义出各种各样的策略,如FTP、文件传输、局域网等等。

(3)BLE低功耗蓝牙核心协议层详解(Bluetooth Core)

① 物理层(PHY)

PHY层用来指定BLE所用的无线频段,调制解调方式和方法等。PHY层做得好不好,直接决定整个BLE芯片的功耗,灵敏度以及selectivity等射频指标。

② 链路层(LL)

LL层是整个BLE协议栈的核心。

LL层要做的事情非常多,比如具体选择哪程度 个射频通道进行通信,怎么识别空中数据包,具体在哪个时间点把数据包发送出去,怎么保证数据的完整性,ACK如何接收,如何进行重传,以及如何对链路进行管理和控制等等。

LL层只负责把数据发出去或者收回来,对数据进行怎样的解析则交给上面的GAP或者ATT。

③ 主机控制接口层(HCI)

HCL是可选的,主要用于两个芯片实现BLE协议栈的场合,用来规范两者之间的通信协议、通信命令等。

④ 通用访问配置文件层(GAP)

主要用来进行广播、扫描和发起连接等。

⑤ 逻辑链路控制及自适应协议层(L2CAP)

L2CAP对LL进行了一次简单封装。LL层只关心传输的数据本身,L2CAP就要区分加密通道还是普通通道,同时还要对连接间隔进行管理。

⑥ 安全管理层(SM)

用来管理BLE连接的加密和安全的。

⑦ 属性协议层(ATT)

简单来说,ATT层用来定义用户命令及命令操作的数据,比如读/写某个数据。

开发者接触最多的就是ATT。BLE引入了attribute(属性)概念,用来描述一条条数据,attribute除了定义数据,还定义该数据可以使用的ATT命令,因此这一层被称为ATT层。

⑧ 通用属性配置文件层(GATT)

用来规范attribute中的数据内容,并用group(分组)的概念进行分类管理。

(4)ATT协议层中的属性(attribute)

ATT(Attribute Protocol)属性层是GATT和GAP的基础,它定义了BLE协议栈上层的数据结构和组织方式。

属性(Attribute)概念是ATT层的核心,ATT层定义了属性的内容,规定了访问属性的方法和权限。以编程的眼光来看,属性是一个数据结构,它包括了数据类型和数据值,就如同C语言结构体的概念,开发者可以设计独特的结构,来描述外部世界实体。

属性包括三种类型:服务项(service)、特征值(characteristic)和描述符。三者之间存在树状包含关系:服务项包含一个或多个特征值,特征值包含一个或多个描述符,多个服务项组织在一起,构成属性规范(Attribute Profile)。

对于常用的属性规范,比如体重计、心率计,SIG(蓝牙技术联盟)做了具体定义,这样的话,只要BLE主从设备均遵守某个Profile来进行设计,那么二者就能够优雅的通信。

(4.1)属性的组成(数据结构)

属性主要由以下四部分组成:

?属性句柄(Attribute Handler):

犹如指向属性实体的指针,可通过属性句柄来访问该属性。它是一个2字节长度的十六进制码,起始于0x0001,系统初始化时各个属性的句柄逐步加1,最大不超过0xFFFF。

属性类型(Attribute Type):

用以区分当前属性是服务项或是特征值等,用UUID来表示。

UUID(universally unique identifier,通用唯一识别码)是一个软件构建标准,并非BLE独有的概念,一个合法的UUID,一定是随机的、全球唯一的,不应该出现两个相同的UUID。

BLE的属性类型是有限的,有四个大类:

  • Primary Service(首要服务项)
  • Secondary Service(次要服务项)
  • Include(包含服务项)
  • Characteristic(特征值)

这些属性类型分别对应了指定的UUID,BLE对这些UUID与属性类型的映射关系做了规定:

  • 0x1800 – 0x26FF :服务项类型
  • 0x2700 – 0x27FF :单位
  • 0x2800 – 0x28FF :属性类型
  • 0x2900 – 0x29FF :描述符类型
  • 0x2A00 – 0x7FFF :特征值类型

假如UUID=0x1800,就表示它是一个首要服务项。

标准的UUID是一串16字节十六进制字符串,但对于一些常用的UUID,为了减少传输的数据量,BLE协议做了一个转换约定,给定一个固定的16字节模板,只设置2个字节为变化量,其他为常量,2字节的UUID在系统内部会被替换,进而转换成标准的16字节UUID。

UUID模板为:

0000XXXX-0000-1000-8000-00805F9B34FB

其中 xxxx 就是变化位,其他为固定位。

如:UUID=0x2A00在系统内部会转换成00002A00-0000-1000-8000-00805F9B34FB。

属性值(Attribute Value):

用于存放数据。

如果该属性是服务项类型或者是特征值声明类型,那么它的属性值就是UUID等信息。如果是普通的特征值,则属性值是用户的数据。

操作特征值里的用户数据,就是对那块内存空间进行读写。

属性权限(Attribute Permissions):

主要有以下四种:

  • 访问权限(Access Permission)- 只读、只写、读写
  • 加密权限(Encryption Permission) – 加密、不加密
  • 认证权限(Authentication Permission) – 需要认证、无需认证
  • 授权权限(Authorization Permission) – 需要授权、无需授权

注:

加密:就是对数据进行加密;

认证:是指相互确认对方身份,BLE中,认证过程就是配对;

授权:授权要求设备为Trusted Device(可信任设备)。在实际使用中,经过配对以后设备即为Untrusted Device——认证,在代码中调用API可以设置设备为Trusted Device——授权。

二. BLE中的GAP和GATT:

蓝牙BLE: GATT Profile 简介(GATT 与 GAP) - 夜行过客 - 博客园

1. 引言:

低功耗蓝牙(BLE)连接都是建立在GATT(Generic Attribute Profile)协议之上。

GATT是一个蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。

2. GAP:

介绍GATT之前,需要了解GAP(Generic Access Profile),它用来控制设备连接和广播。GAP使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与其他设备进行交互。

2.1 设备角色

GAP给设备定义了若干角色,主要的两个是:

① 外围设备(Peripheral):比如手环。一般是小、简单、低功耗设备,用来提供数据,并连接到一个强大的中心设备上。

② 中心设备(Central):比如手机。用来连接其他外围设备。

2.2 广播数据

在 GAP 中外围设备通过两种方式向外广播数据:?Advertising Data Payload(广播数据)和?Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。

?从图中我们可以清晰看出广播数据和扫描回复数据是怎么工作的。外围设备会设定一个广播间隔,每个广播间隔中,它会重新发送自己的广播数据。广播间隔越长,越省电,同时也不太容易扫描到。

大部分情况下,外设通过广播自己来让中心设备发现自己,并建立GATT连接,从而进行更多的数据交换。

也有些情况是不需要连接的,只要外设广播自己的数据即可。

用这种方式主要目的是让外围设备把自己的信息发送给多个中心设备。因为基于GATT连接方式的,只能是一个外设连接一个中心设备。

3. GATT

GATT 连接,必须先经过GAP协议。

一旦两个设备建立起了连接,GATT 就开始起作用了。

中心设备和外设需要双向通信的话,唯一的方式就是建立GATT 连接。

GATT 定义两个BLE设备通过Service和Characteristic进行通信。

GATT使用ATT协议,把Service、Characteristic以及对应的数据保存在一个查找表中,次查找表使用16bit ID作为每一项的索引。

GATT 连接需要注意的是:GATT 连接是独占的,即一个BLE外设同时只能被一个中心设备连接,一旦外设被连接,它就会立马停止广播,这样它就对其他设备不可见了。

一旦建立了连接,通信就是双向的了。而前边的GAP广播通信则是单向的(外设进行广播)。

如果要让两个外设进行通信,就只能通过中心设备中转。

3.1 GATT通信事务

GATT通信的双方是C/S关系。

外设作为GATT服务端(Server),维持了ATT的查找表以及service和characteristic的定义。

中心设备是GATT客户端(Client),它向Server发起请求。

需要注意,所有的通信事件,都是由客户端(也叫主设备,Master)发起,并且接收服务端(也叫从设备,Slave)的响应。

一旦建立连接,外设会给中心设备建议一个连接间隔(Connection Interval),这样中心设备就会在每个间隔尝试去重新连接,检查是否有新数据。这个连接间隔只是个建议。

下图展示一个外设(GATT服务端)和中心设备(GATT客户端)之间的数据交流流程,可以看到的是,每次都是主设备发起请求:

3.2 GATT结构

GATT事务是建立在嵌套的Profiles,Services和Characteristics之上的,如下所示:

Profile

一种规范,一种标准的通信协议。每个profile中会包含多个service服务,每个service代表该从机的一种能力。

Service

一种服务,也就是从机的能力。例如,蓝牙从机的电量信息服务、系统信息服务等。每个service中又包含多个characteristic特征值,每个具体的characteristic才是BLE通信的主题。

Characteristic

特征值,BLE主从机的通信均是通过characteristic来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。

举个例子,Heart Rate Measurement Characteristic。

这个 Characteristic 是Heart Rate Service必须实现的,它的UUID为0x2A37。它的数据结构是,开始8bit定义心率数据格式,后边的是对应格式的实际心率数据。

UUID

统一标识码,service 和 characteristic 都需要一个唯一的UUID来标识。

三.?一些常见术语概念

1. ATT PDU(属性协议)

认识BLE 5协议栈 —— 属性协议层 – SYQ

在ATT层协议框架内,拥有一组属性的设备称为服务端(Server),读写该属性值的设备称为客户端(Client),Server和Client通过ATT PDU进行交互。属性协议共有6种:

属性PDU方向触发响应
CommandClient -> Server
RequestClient -> ServerResponse
ResponseServer -> Client
NotificationServer -> Client
IndicationServer -> ClientConfirmation
ConfirmationClient -> Server

解释:

  • 客户端发送Request,服务器需要返回一个Response,表明服务器收到了。
  • 服务器发送Indication,客户端需要返回一个Confirmation,表明客户端收到了。
  • 以上两种方式,均是单线程操作,即下一个Request/Indication操作需要在上一个操作收到Response/Confirmation之后才能开始。
  • 客户端发送Command,服务器无需任何返回。
  • 服务器发送Notification,客户端无需任何返回。

2. GAP Bond管理

gap_bond_manager_and_le_secure_connections

GAP Bond Manager?是一个可配置模块,使用Bond Manager后应用程序可以减少大部分安全机制。

术语描述
配对(Pairing)交换密钥的过程
加密(Encryption)0x02
认证(Authentication)使用中间人(MITM)保护完成的配对
Bonding将密钥存储在非易失性存储器中
授权(Authorization)除了认证之外,还需要额外的应用级密钥交换
OOB(Out of band)密钥不是通过空中交换,而是通过串行端口或NFC等其他来源进行交换。这也提供了MITM保护。
MITM(Man in the Middle protection)这可以防止攻击者收听通过空中传输的密钥来破坏加密。
只是工作(Just work)配对方法,其中密钥在没有MITM的情况下通过空中传送

在程序中使用GAPBondMgr实现,过程如下:

  • 配对过程通过选择配对模式中描述的方法交换密钥。
  • 使用步骤1的密钥加密连接。
  • 绑定过程将密钥存储在安全闪存(SNV)中。
  • 重新连接时,使用存储在SNV中的密钥来加密连接。

使用GAPBondMgr

使用GAPBondMgr模块的一般步骤:

1.?配置堆栈以包括GAPBondMgr功能,如果需要安全连接。

2.?堆栈还必须配置为使用1或2个SNV界面。

3.?如果使用安全连接,则PDU大小必须大于等于69,可用于安全连接的最小堆大小为3690。

4.?根据需要初始化其参数来配置GAPBondMgr。

5.?使用GAPBondMgr注册应用程序回调,以便应用程序可以与GAPBondMgr通信并通知事件。

//Register with bond manager after starting device
GAPBondMgr_Register(&bondmanager_callbacks);

一旦GAPBondMgr被配置,它主要从应用程序的角度自主运行。当建立连接时,根据初始化期间设置的配置参数启动配对和绑定,并根据需要通过定义的回调与应用程序通信。

GAPBondMgr与应用程序之间的大多数通信都是通过在步骤5中注册的回调发生的。

GAPBondMgr与此应用程序之间的大多数通信都是通过在步骤5中注册的回调发生的。 下图是GAPBondMgr的流程图示例,通知应用程序配对已经完成。对于各种其他事件的发生也是用相同的方法,并将在后面部分进行扩展。

四. 如何通过无线发送一个数据包

深入浅出低功耗蓝牙(BLE)协议栈_iini的博客-CSDN博客

下面以如何发送一个数据包为例来讲解BLE协议栈各层是如何紧密配合,以完成发送任务的。

假设有设备A、B,A要把自己当前的电量值83%(十六进制表示为0x53)发给设备B,该怎么做呢?对开发者而言,他希望调用一个简单的API就能完成这件事,比如 send(0x53),实际上BLE协议栈就是这样设计的。开发者只需调用API,其余事情BLE协议栈帮你搞定。

很多人会想,BLE协议栈是不是直接在物理层就把0x53发出去了,就像下图所示:

实际不是这样的。

首先他没有考虑用哪一个射频信道来进行传输。在不更改API的情况下,我们只能对协议栈进行分层,因此引入 LL层,开发者还是调用?send(0x53),send(0x53)?里再调用send_LL(0x53, 2402M)(注:2402M为信道频率)。

这里还有一个问题,设备B怎么知道这个数据包是发给自己的还是其他人的,为此BLE引入access?address?概念,用来指明接受者身份。(其中,0x8E89BED6这个access?address比较特殊,它表示要发给周边所有设备,即广播)。如果要一对一进行通信(BLE称其为连接),即设备A的数据包只能设备B接收,同样设备B的数据包只能设备A接收,那么就必须生成一个独特的随机access?address?以标识设备A和设备B两者之间的连接。

广播方式

我们先来看一下简单的广播情况,这种情况下,我们把设备A叫advertiser(广播者),设备B叫scanner或者observer(扫描者)。广播状态下设备A的LL层API将变成 send_LL(0x53,2402M, 0x8E89BED6)。由于设备B可以同时接收到很多设备的广播,因此数据包还必须包含设备A的device address(0xE1022AAB753B)以确认该广播包来自设备A,为此send_LL参数需要变成(0x53,2402M, 0x8E89BED6, 0xE1022AAB753B)。LL层还要检查数据的完整性,为此引入CRC24对数据包进行校验(假设为0xB2C78E)。同时为了调制解调电路工作更高效,每一个数据包的最前面会加上1个字节的帧头(一般为0x55或0xAA)。

这样,整个空中包就变成:(空中包用小端模式表示)

上面这个数据包还有如下问题:

  • (1)没有对数据包进行分类组织,设备B无法找到自己想要的数据0x53。为此需要在access?address之后加入两个字段:LL?header和长度字节。LL header用来表示数据包的LL类型,长度字节用来指明payload的长度。
  • (2)设备B什么时候开启射频窗口以接收空中数据包呢?如上图所示,只有case3的情况,通信才能成功,即设备A的数据包在空中传输时,设备B正好打开射频接收窗口,此时通信才能成功,换句话说,LL层还必须定义通信时序
  • (3)当设备B拿到数据0x53后,该如何解析这个数据呢?这就是GAP层要做的工作,GAP层引入了LTV(Length-Type-Value)结构来定义数据。比如020105, 02-长度,01-类型,05-值。由于广播包最大只能为31个字节,它能定义数据类型极其有限,像上边说的电量,GAP就没有定义,因此要通过广播方式把电量数据发出去,只能使用供应商自定义数据类型0xFF,即04FF590053(小端表示),其中04-长度,FF-自定义数据类型,0x0059-供应商ID(自定义数据中的强制字段,),0x53-数据(设备双方约定0x53就是表示电量)。

最终,空中传输的数据包变为:(小端表示)

AA D6BE898E 60 0E 3B75AB2A02E1 02010504FF5900?53?8EC7B2

  • AA – 前导帧(preamble)
  • D6BE898E – 访问地址(access address)
  • 60 – LL帧头字段(LL header)
  • 0E – 有效数据包长度(payload length)
  • 3B75AB2A02E1 – 广播者设备地址(advertiser address)
  • 02010504FF590053 – 广播数据
  • 8EC7B2 – CRC24值

经过上边过程的封装(PHY、LL和GAP),就可以发送广播包了,但广播包携带的信息极其有限,而且还有如下几大限制:

(1)无法进行一对一通信;

(2)由于不支持组包和拆包,因此无法传输大数据;

(3)通信不可靠。广播信道不能太多,否则将导致扫描效率低下。为此,BLE只使用37(2402MHz)、38(2426MHz)、39(2480MHz)三个信道进行广播和扫描,因此广播不支持跳频。由于广播是一对多,所以广播也无法支持ACK,这些都使得广播通信变得不可靠。

跳频:收发双方按照同一时序不同变换频率,这个频率的变化规律一般由一个伪随机的序列控制,通信前要先同步,使得双方的序列同步。

(4)扫描端功耗高。由于扫描端不知道设备端何时广播,也不知道设备端选用哪个频道进行广播,扫描端只能拉长扫描窗口时间,并同时对37/38/39三个通道进行扫描,这样功耗就会比较高。

而连接则可以很好解决上述问题。

连接方式

所谓设备A和设备B建立蓝牙连接,就是指A、B两者“同步”成功,具体包含以下几方面:

  • A、B对接下来要使用的物理通道达成一致;
  • A、B双方建立一个共同的时间锚点,也就是说把双方的时间原点变为同一个点;
  • A、B两者时钟同步成功,即双方都知道什么时候发送/接收数据;

连接成功后,A、B通信流程如下所示:

如上图所示,一旦设备A和设备B连接成功(此种情况下,我们把设备A称为Master或者Central,把设备B称为Slave或者Peripheral),设备A将周期性以CI(connection interval)为间隔向设备B发送数据包,而设备B也周期性地以CI为间隔打开射频接收窗口以接收设备A的数据包。同时按照蓝牙spec要求,设备B收到设备A数据包150us后,设备B切换到发送状态,把自己的数据发给设备A;设备A则切换到接收状态,接收设备B发过来的数据。由此可见,连接状态下,设备A和设备B的射频发送和接收窗口都是周期性地有计划地开和关,而且开的时间非常短,从而大大减低系统功耗并大大提高系统效率。

现在我们看看连接状态下是如何把数据0x53发送出去的,从中大家可以体会到蓝牙协议栈分层的妙处。

(1)对开发者,很简单,他只需调用?send(0x53);

(2)GATT层定义数据的类型和分组,我们假设用 0x0013?来表示电量这种数据类型,这样GATT层就把数据打包成 :130053(小端);

(3)ATT层用来选择具体的通信命令,比如read/write/notify/indicate等,这里选择notify命令0x1B,这样数据包就变成了:1B130053;

(4)L2CAP用来指定CI(connection?interval,连接间隔),比如每10ms同步一次(CI不体现在数据包中),同时指定逻辑通道编号0004(表示ATT命令),最后把ATT数据长度0x0004加在包头,这样数据就变成:040004001B130053;

(5)LL层要做很多事。

① 首先LL层需要指定用哪个物理信道进行传输(物理信道不体现在数据包中),

② 然后再给此连接分配一个Access address(0x50655DAB)以标识此连接只为设备A和设备B直连服务,

③ 然后加上LL header和payload length字段,LL header标识此packet为数据packet,而不是control packet等,payload length为整个L2CAP字段的长度,最后加上CRC24字段,以保证整个packet的数据完整性,

所以数据包最后变成:

AAAB5D65501E08040004001B130053D550F6

  • AA – 前导帧(preamble)
  • 0x50655DAB – 访问地址(access address)
  • 1E – LL帧头字段(LL header)
  • 08 – 有效数据包长度(payload length)
  • 04000400 – ATT数据长度,以及L2CAP通道编号
  • 1B – notify command
  • 0x0013 – 电量数据handle
  • 0x53 – 真正要发送的电量数据
  • 0xF650D5 – CRC24值

虽然开发者只调用了 send(0x53),但由于低功耗蓝牙协议栈层层打包,最后空中实际传输的数据将变成下图所示的模样,这就既满足了低功耗蓝牙通信的需求,又让用户API变得简单,可谓一箭双雕!

上面只是对BLE协议栈实现原理做了一个简单概述。对很多开发者来说,他们也不关心BLE协议栈是如何实现的,他们更关心的是BLE协议栈的使用,即怎么开发一个BLE应用。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 23:07:58  更:2022-03-15 23:10:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 2:58:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码