ble 理论(15)ble 连接详解

1 ble连接事件

进入连接状态是广播状态下的 CONNECT_REQ PDU 的发送和接收。当进入连接状态后,两个设备就担任不同的角色,发送 CONNECT_REQ的成为主机,接收 CONNECT_REQ 的成为从机。之后就会在这两个设备之间发生连接事件
和广播事件一样,每隔一定的时间连接事件由主机从数据信道发送一个数据包,从机接到数据如果有数据发送需要在 150±2 µs 做成应答。也就是说每一个连接事件中至少包含主机发送的一个包,从机
可以不发送包。

  • 连接事件的时间由两个参数决定:connection event interval(connInterval), and slave latency (connSlaveLatency).即连接间隔和从机潜伏期
  • anchor point 连接事件开始的点叫做锚点(The start of a connection event is called an anchor point)。主机在锚点开始连接事件,从机需要在锚点前进入侦听状态。
  • connEventCounter 这是连接事件计数器,在协议中规定

Both the master and the slave shall have a 16-bit connection event counter (connEventCounter) for each Link Layer connection.

主机和从机都有一个 16 位的连接事件计数器,这个值是为了这两个设备之间的同步。这个值只要是连接事件参数就会加1,当然第一个连接事件时这个值为 0 而不是 1。无论从机潜伏期的值是多少,只有从机接收到主机的连接事件这个值在从机里面就要加 1。当这个值到了 0xFFFF 时,会翻转到 0x0000,重新开始计算

2 监管超时

如果连接状态下,很长时间都没有连接事件发生,或者连接事件发送总是得不到从机的应答,是不是该考虑连接出了问题呢?在协议中也有规定一个参数——连接监管超时 Connection supervision timeout (connSupervisionTimeout)。这个值是 10ms 的倍数,并且在100ms~30.0s 之 间 , 同 时 它 必 须 大 于 (1 + connSlaveLatency) connInterval,这应该好理解,从机潜伏期是双方沟通和允许的事情,所以超时间一定要大于上面表达式才行。这里有个特殊情况,在发送 CONNECT_REQ 之 后 , 如 果 链 路 层 的 连 接 超 时 时 间 达 到6connInterval,那么将认为连接建立失败。我还是将协议的原文复制
一下吧!避免歪曲理解

If the Link Layer connection supervision timer reaches 6 * connInterval before the connection is established, the connection shall be considered lost. This enables fast termination of connections that fail to establish.

3 连接事件传输窗口

在 这 我 还 是 先 讲 一 下CONNECT_REQ 的报文组成。如图 2-35 为 CONNECT_REQ PDU 的有效
组成
在这里插入图片描述
为 LLData 的组成结构
在这里插入图片描述
LLData 包含有 10 个区域:

  • AA 区域共有 4 个字节。”AA”是 Access Address 接入地址的两个头字母,前面有提到连接状态下的接入地址是有主机在连 接请求包中提供
  • CRCInit 区域共有 3 个字节。是连接状态下的 CRC 校验的移位
    寄存器的初始值。
  • WinSize 区域共有 1 个字节。它为传输窗口的时间,而且这个 值乘以 1.25ms 才是真正的传输窗口时间。即:

transmitWindowSize = WinSize * 1.25 ms。它是 1.25ms 的倍数,
范围:[1.25ms,MIN(10ms, connInterval - 1.25 ms)]

  • WinOffset 区域共有 2 个字节。它是传输窗口偏移的时间,同 样这个值需要乘以 1.25ms 才是真正的传输窗口偏移时间。 这个参数其实只在第一连接事件发生前或者连接参数更新时用一次,之后的时间主要就是连接间隔和扫描窗口控制。范围:

transmitWindowOffset = WinOffset * 1.25 ms 它是 1.25ms 的倍数, 范围:[0, connInterval]

  • Interval 区域共有 2 个字节。这个就是传说中的连接间隔时间 了。
  • 时间为:  connInterval = Interval *1.25 ms 它是 1.25ms 的倍数,范围: [7.5ms,4.0S]
  • Latency 区域共有 2 个字节。这个就是从机潜伏次数,这个是 次数不是时间啊!什么作用呢?就是从机没有必要对于每一个主机的连接事件都进行应答,例如假设 connSlaveLatency=5 , 那么连续 5 个连接事件,如果从机本身没有数据需要发送,那么这个 5 个事件从机可以不用搭理,主机也不会认为连接 出了问题。
  • connSlaveLatency = Latency 范围:[0, MIN(((connSupervisionTimeout / connInterval) - 1),500)]
  • Timeout 区域共有 2 个字节。这个时间前面有提到它是 10ms 的倍数。所以真正的时间为:

connSupervisionTimeout = Timeout * 10 ms
范围[MAX(100 ms, (1 + connSlaveLatency) * connInterval),32.0s]

  • ChM 区域共有 5 个字节。它就是信道地图了,具体看信道章 节。
  • Hop 区域共有 5bits。这是 5bits,这是 5bits,重要的事情说 3 遍。这个在自适应调频中使用的调频增量。
  • SCA 区域共有 3bits。这个东东就是主机的时钟精度,这个是 最难用的一个参数了,在传输窗口扩展中会用到这个参数。 这 3 个
    bit 表达能力是有限的,所以在协议中有一张表,如图
    在这里插入图片描述
    也就是说传输窗口其实是在 CONNECT_REQ 包中的,并且窗口偏移(WinOffset)只有是从广播态进入连接态时使用,或者在参数更新时使用,而 WinSize 时间是每个连接事件都必须使用的

4 连接状态–主机

在第一个连接事件中,锚点是由 CONNECT_REQ PDU 中的参数决定的。当主机发送完 CONNECT_REQ 报文之后,接着发送第一个连接事件的报文,而从机接到 CONNECT_REQ 报文后,做好进入连接状态的准备工作后,根据 CONNECT_REQ 中的参数,决定开始侦听的时间,但是必须保证,主机在锚点前从机必须已经进入侦听状态。怎么保证这个时间点呢? 来张图看看协议中是怎么规定的
在这里插入图片描述
协议中有这么一段:

The CONNECT_REQ PDU includes three parameters used to determine the transmit
window. The transmit window starts at transmitWindowOffset+ 1.25 ms after the
end of the CONNECT_REQ PDU, and the transmitWindowSize parameter shall define
the size of the transmit window.The connIntervalis used in the calculation of the
maximum offset and size of the transmit window.
Therefore the start of the first packet will be no earlier than 1.25 ms + transmitWin-
dowOffset and no later than 1.25 ms + transmitWindowOffset + transmitWindowSize
after the end of the CONNECT_REQ PDU transmitted in the advertising channel.

从上可知传输偏移一定是在 1.25ms 之后。也就是说,连接状态的第一包数据传输一定是在
**[1.25 ms + transmitWindowOffset, 1.25ms + transmitWindowOffset + transmitWindowSize]**之间。

下图 2-28为传输偏移不为 0 的连接示意图,下图 2-39 为传输偏移为 0 的情况
在这里插入图片描述

5 连接状态-- 从机

对于主机来说控制着连接状态下的几乎所有权利,可是对于配合者的从机却是有些难办。如果理想状态,晶振没有任何偏差,那么有了这个时序,就很容易完成这个程序的编写。事实总是很残酷的,晶
振总有一些漂移的,这样就会带来主机肯定是发送了连接事件中的第一个报文,但是从机并不一定能接收得到,所以看看从机如果在第一个连接事件中没有接收到数据报文的话,时间又是怎么控制的,有图
有真相,见图 2-40
在这里插入图片描述
先讲述一下从机进入连接状态的过程:对于从机接收到CONNECT_REQ 之后,协议留了至少 1.25ms 的时间让其准备进入连接状态,进入之后偏移一个传输窗口的时间,进而进入扫描窗口,开始侦听空中的包,看是否有自己需要的报文,所以在上面的图中传输窗口都是用虚线的,也就是说传输口规定了最大时间,但是并不一定要等这么久的时间,收到数据就可以去处理,并开始计时连接间隔时间,等到连接间隔时间到,再次进入扫描窗口,侦听报文
在这再重点说几个问题:

  • 什么情况表示从机接收到了第一个连接事件?

The first packet received, regardless of a valid CRC match (i.e., only the access code matches), in the Connection State by the slave determines the anchor point for the first connection event, and therefore the timings of all future connection events in this connection

理解是第一个包接收时,无论 CRC 是否正确,只需要接入地址正确,在连接状态下锚点由从机接收的第一个连接事件报文决定,并决定了将来的锚点。

  • 连接间隔时连接间隔时间的起点在哪?
    连接间隔时间的起点有两个位置:

(1)当从机接收报文成功,连接间隔时间起点,就是接收到报文的那个时刻,当然对于 nrf51822 来说,就是 Radio 的END事件产生的
(2)当从机接收报文失败,连接间隔时间起点,就是扫描窗口的开始时刻。

  • 从机在传输窗口中没有接收到第一个连接事件?
    这种情况,从机不得不等待连接间隔时间后再次进入传输窗口,等待接收下一个报文。虽然接收失败,但是还是有几点要注意的:

连接事件计数值 connEventCount 这个值还是得加 1 的。
数据通道的频率还得接着跳到下一个频

6 连接事件关闭

这里是连接事件关闭,不是连接关闭啊!如果主机和从机之间没有过多的数据发送,那么连接事件仅仅是例行事件,主机发送一个报文,从机要么回应要么不回应,主机会关闭连接事件。但是如果主机或者从机在一个连接事件中有多个数据需要发送时,在前面数据报文中有提到 MD 这个标志(图 2-11)。这个标志将决定连接事件的关闭,如图 2-41
在这里插入图片描述

7 窗口扩展

这是我在软件中最难处理的问题,到现在都还没有处理好。前面有提到晶振总是有漂移的,那么从机希望的锚点,不一定按时出现,要么提前要么推迟,不管提前或者推迟,如果还是在传输窗口中也好,但是如果不在那就麻烦了,这个时候就要用到窗口扩展了。在 CONNECT_REQ PDU 报文中,主机会将自己的时钟精度发给从机,从机就需要通过主机和从机的时钟精度的偏差来计算出需要扩展的时间是多少。这个扩展的时间就是扩展给扫描窗口用的。相当于把扫描窗口的时间加大。既然要加大为什么一定要计算呢?这就是低功耗的魅力了,每一个环节都在进行功耗的节省,而射频是最耗能量的,
所以得精打细算
不过不幸运的是,我读不懂协议汇中的意思,这里贴出原文并留
有空白页,如果有谁读到了这节,有自己的见解的话,希望能在下面
做一下记录,或者告诉我。特别是红色部分,没明白什么意思。
计算公式如下:

[(Master PPM + Slave PPM)/106 ] * 连接间隔时间 + 2
上式还没用用于程序,所以也还没有验证其正确性

Because of sleep clock accuracies, there is uncertainty in the slave of the exact timing
of the master’s anchor point. Therefore the slave is required to re-synchronize to the
master’s anchor point at each connection event where it listens for the master. If the
slave receives a packet from the master regardless of a CRC match, the slave shall
update its anchor point. The slave calculates the time when the master will send the
first packet of a connection event (slaveExpectedAnchorPoint) taking clock jittering,
and in the case of connection setup or a connection parameter update the transmit
window, into account. The slave shall also use the masters sleep clock accuracy
(masterSCA) from the CONNECT_REQ PDU, together with its own sleep clock
accuracy (slaveSCA) and the anchor point of the last connection event where it
received a packet from the master (timeSinceLastAnchor) to calculate the time it
needs to receive. The increase in listening time is called the window widening.
Assuming the clock inaccuracies are purely given in parts per million (ppm), it is
calculated as follows:
windowWidening = ((masterSCA + slaveSCA) / 1000000) * timeSinceLastAnchor
During connection setup or during a connection parameter update, the slave should
listen for windowWidening before the start of the transmit window and until
windowWidening after the end of the transmitWindow for the master’s anchor
point. At each subsequent connection event, the slave should listen for
windowWidening before the start of the slaveExpectedAnchorPoint and until
windowWidening after slaveExpectedAnchorPoint for the master’s anchor poin

8 软件设计连接态流程图

这里再说一下低功耗蓝牙中的应答事件并不一定要在同一个连接事件中立刻应答,例如主机在连接事件中发送了一个请求版本信息的请求,从机可以下回应一个空包,等到下一个连接事件时,从机再发送版本信息给主机。也就是说每次连接事件中,从机应答的都是主机在上一个连接事件中提出的问题,而主机在连接事件中发送的报文也有可能是从机上一个连接事件中提出的问题。之所以这样做是因为,
在 150±2 µs 完成数据包的解析和发送包的准备是比较困难的。连接状态下的状态机相对比广播状态并没有难多少。但是却也有些抓狂的事情:
扫描窗口的把握
 连接间隔时间起点的把控
 自适应调频和白化控制
 报文上传到 HOST 层同时 HOST 准备发送报文
在连接状态,我用的时钟是 RTC 时钟,这里其实还有个问题,RTC时钟最小的定时单位是 30us,而实际上主从的时钟精度加起来计算出来的时钟偏差都没有 30us,所以我在程序处理时,直接将扫描窗
口扩展了两个单位,也就是 60us,这肯定是没有问题的,只是功耗增加。流程图 2-42 如下
在这里插入图片描述

9 主从连接参数的修改

“连接参数更新请求”命令可以让从设备更新链路层的连接参数,如下图所示。这些参数包括连接间隔(从设备希望主设备允许从设备发送数据包的频率)、从设备延迟(从设备能够忽略主设备的连接事件的最大值)以及监控超时。
在这里插入图片描述

在连接中,如果从设备希望修改当前的连接参数则可以使用该命令。比方说,如果连接事件的间隔有可能太快了,导致过多的电量浪费。这在从设备时延很大时没有问题,但如果不是这样,从设备将会频繁的侦听链路。这在一些情况下是必要的,例如设备间首次绑定、互发多个数据包、探索服务和设备特性等。但在很多其他情况下,尽可能地减少从设备必须侦听连接事件的数量对提高电池寿命至关重要。

连接参数更新请求命令仅用于从设备向主设备发送,这是由于主设备随时都能启动链路层连接参数更新控制(Connection Parameter Update Control)规程。如果该命令由主设备发送,从设备会将其视为一个错误,并返回带有“命令不理解”原因代码的“命令拒绝”命令。

从设备可以在任何时候发送该命令;收到该信息的主设备如果可以修改连接参数,则将返回“连接参数更新响应”(Connection Parameter Update Response),其中的结果代码设为“接受(accepted)”。随后,主设备将会启动链路层连接参数更新控制规程。

当然,如果主设备不同意从设备的请求参数,它可以发送结果代码为“拒绝(rejected)”的连接参数更新响应命令以拒绝请求。此时从设备有两个选择:要么接受主设备希望的正在使用的连接参数,要么终止连接。终止连接的做法咋看起来可能让人觉得很激进,但是,假如使用当前的参数从设备将会在一周内耗尽电量,而使用请求的参数则可以持续数年,很明显,合理的选择只有一个。

修改连接参数时,如果要减少主设备拒绝从设备请求的可能性,可以在请求里设置一个可接受的参数范围。经过精心设计的从设备会乐意接受很宽的参数范围。由于主设备可能正忙于实时会话音频连接或者高质量语音连接等任务,它可以接受一定范围内的连接间隔参数。设备可接受的间隔参数会根据当前任务的不同而不同,可能有别于上一次设备连接时的参数。

要提高主设备接受连接参数的机率,还有个方法是从设备提供一个合理的从设备延迟。主设备可以选择最合适的连接事件间隔,从设备则使用最佳功耗的从设备延迟参数。

举个例子,如果从设备想每 600ms 同步一次,它可以请求范围 100ms ~ 750ms 的连接间隔参数,并带上从设备延迟5。如果主设备选择 100ms,则从设备每6个连接事件同步一次;如果主设备选择 200ms,则从设备每 3 个连接事件同步一次,实现其所期望的 600ms 间隔;如果主设备选择 300ms,则从设备忽略每隔一个连接事件同步一次;如果主设备选择 400ms,则从设备每 400ms 同步一次。

q :687360507:

  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Angular Intro.js 是一个 AngularJS 模块,用于集成 Intro.js 库,以提供网站或应用程序的新手引导和演示。下面是使用步骤: 1. 安装 Angular Intro.js:通过 npm 安装 Angular Intro.js 模块。 ``` npm install angular-intro.js --save ``` 2. 引入 Intro.js 库:在项目中引入 Intro.js 库,可以通过 npm 安装或直接使用 CDN 引入。 ``` <script src="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/intro.min.js"></script> ``` 3. 引入 Angular Intro.js 模块:在 AngularJS 应用程序中引入 Angular Intro.js 模块。 ``` angular.module('myApp', ['angular-intro']); ``` 4. 在 HTML 中使用:在 HTML 中使用指令来添加新手引导和演示。 ``` <div introjs intro-options="options"> <p>这是一个新手引导示例</p> <button ng-click="showStep2()">下一步</button> </div> ``` 上面的代码中,`introjs` 指令告诉 Angular Intro.js 应该在这个元素上启用引导,`intro-options` 属性包含 Intro.js 配置选项,`showStep2()` 是一个 AngularJS 控制器中的函数,用于显示下一个步骤。 5. 在控制器中配置选项和方法:在 AngularJS 控制器中配置 Intro.js 选项和方法。 ``` angular.module('myApp').controller('myCtrl', function($scope) { $scope.options = { steps: [ { element: document.querySelector('#step1'), intro: '这是第一步' }, { element: document.querySelector('#step2'), intro: '这是第二步' } ] }; $scope.showStep2 = function() { introJs().goToStep(2).start(); }; }); ``` 上面的代码中,`steps` 选项包含 Intro.js 步骤对象,每个步骤是一个包含 `element` 和 `intro` 属性的对象。`showStep2()` 函数使用 Intro.js 方法来显示第二步。 以上是 Angular Intro.js 的简单使用方法,可以根据需要进行配置和扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值