这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
cc2640r2f:gap [2017/09/01 20:21] long |
cc2640r2f:gap [2021/06/22 23:14] (当前版本) |
||
---|---|---|---|
行 1: | 行 1: | ||
< | < | ||
+ | |||
# 概述 # | # 概述 # | ||
- | GAP分层负责设备建立连接相关功能,包括设备发现、数据链路建立、终止,初始化安全管理和设备配置,参见下图。 | + | |
- | ![](http:// | + | GAP 分层负责设备建立连接的相关功能,包括设备发现、数据链路建立、终止、初始化安全管理和设备配置,参见下图 |
- | 在`Standby`状态,双方设备都处于未连接状态,`Advertiser`尝试广播数据,`Scanner`接收到广播数据后尝试进行扫描请求,并且得到扫描回复。此时`Scanner`产生连接意图,转变成`Initiator`发送连接请求,成功连接后发送广播的`Advertiser`作为`Master`,进行连接请求的`Initiator`成为`Slave`. | + | |
+ | ![](http:// | ||
+ | |||
+ | 图1. GAP 分层的建立连接的示意图 | ||
+ | |||
+ | 在 `Standby` 状态,双方设备都处于未连接状态。`Advertiser` 尝试广播数据,`Scanner` 接收到广播数据后尝试进行扫描请求,并且得到扫描回复。此时 `Scanner` 产生连接意图,转变成 `Initiator` 发送连接请求,成功连接后发送广播的 `Advertiser` 作为 `Master` ,进行连接请求的 `Initiator` 成为 `Slave`。 | ||
- Standby:复位后设备处于初始空闲状态。 | - Standby:复位后设备处于初始空闲状态。 | ||
- | - Advertiser:设备正在通过特定数据进行广告,让任何Initiator设备知道它是可一个连接设备(此广告数据负载可以包含设备地址,和一些其他数据,如设备名称)。 | + | - Advertiser:设备正在通过特定数据进行广告,让任何 Initiator 设备知道它是可一个连接设备(此广告数据负载可以包含设备地址和一些其他数据,如设备名称)。 |
- Scanner:扫描设备收到广告后,向广告客户发送扫描请求。广播者响应扫描响应。这个过程称为设备发现。当然扫描设备已经知道广告设备可以发起与其的建立连接。 | - Scanner:扫描设备收到广告后,向广告客户发送扫描请求。广播者响应扫描响应。这个过程称为设备发现。当然扫描设备已经知道广告设备可以发起与其的建立连接。 | ||
- | - Initiator:启动时,启动器必须指定要连接的对等设备地址。如果接收到与对等设备的该地址匹配的广告,则发起设备然后发送与广告设备建立与连接参数中描述的连接参数的连接的请求 | + | - Initiator:启动时,启动器必须指定要连接的对等设备地址。如果接收到与对等设备地址匹配的广告,则发起设备发送连接请求,该请求包含与广告设备连接所需的连接参数。 |
- | - Master/ | + | - Master/ |
## 抓包理解以上连接过程 ## | ## 抓包理解以上连接过程 ## | ||
- | * Advertiser进行广播 | + | |
+ | * Advertiser 进行广播 | ||
![](http:// | ![](http:// | ||
- | * Scanner进行连接请求并且获得回复 | + | |
+ | * Scanner 进行连接请求并且获得回复 | ||
![](http:// | ![](http:// | ||
![](http:// | ![](http:// | ||
+ | |||
* 连接请求 | * 连接请求 | ||
+ | |||
![](http:// | ![](http:// | ||
## 连接参数 ## | ## 连接参数 ## | ||
- | 连接参数主要是用以Initiator通过 连接请求 建立连接时候的用到配置参数。 | + | 连接参数是 Initiator 通过连接请求建立连接时的配置参数。 |
+ | |||
+ | ** Connect Interval ** | ||
+ | |||
+ | 蓝牙采用跳频通信,连接的两个设备在某个固定时间切换到某个固定信道进行通信,链路层控制着信道切换。 | ||
+ | |||
+ | 建立连接后的通信数据被统一定义为 `Connection event` 。如果没有应用数据发送或者接收,那么链路层也会继续交换数据维护着这个链接。连接间隔是指以 `1.25ms` 为单位,两次 `Connection event` 的时间总和。其值可以从 6-3200 ,也就是 7.5ms 到 4.0s 。 | ||
- | **Connect Interval** | ||
- | 对于蓝牙,采用跳频通信,连接的两个设备在某个固定时间切换到某个固定信道进行通信。链路层控制着这里的信道切换。建立连接后的通信数据被我们统一定义为`Connection event`, | ||
![](http:// | ![](http:// | ||
+ | |||
+ | 图2. 连接间隔 | ||
+ | |||
不同的应用需要不同的连接间隔,主要是从功耗进行考虑。 | 不同的应用需要不同的连接间隔,主要是从功耗进行考虑。 | ||
- | **Slave Latency** | + | ** Slave Latency ** |
- | Slave Latency表在在没有数据发送的时候可以选择跳过connect event,一个连接时间的发生都是master发送一个通知,设备回复响应然后发送数据,但是没有数据的时候假设我们设置了Slave Latency = 3;那么当master发送通知的时候,slave可以3次不响应,一直保持在深度休眠状态,这样就不会产生Connect event事件,从而更加省电。 | + | |
+ | Slave Latency | ||
![](http:// | ![](http:// | ||
- | **Supervision Time-out** | + | 图3. Slave Latency 的功能示意图 |
- | Supervision Time-out就是两次成功的connect event之间的最长事件,如果超出改时间没有发生connect event,则双方设备终止连接,并进入到未连接状态。该参数可以设置在100ms到32S之间。但是需要注意的是,超时监控时间必须大于有效连接间隔。什么是有效连接间隔,其实就是两次成功的connect event之间的时间,假设Slave Latency = 0,connect interval = 5ms。我们设置的超时监控总不可能比5ms还小,这样就永远都处于超时状态。可以通过下面公式计算超时监控的时间。 | + | |
+ | ** Supervision Time-out ** | ||
+ | | ||
+ | Supervision Time-out 就是两次成功的 connect event 之间的最长事件。如果超出时间没有发生 connect event ,则双方设备终止连接,并进入到未连接状态。该参数可以设置在 100ms 到 32S 之间,需要注意的是超时监控时间必须大于有效连接间隔。 | ||
+ | |||
+ | 什么是有效连接间隔,其实就是两次成功的 connect event 之间的时间。假设 Slave Latency = 0,connect interval = 5ms 。设置的超时监控总不可能比 5ms 还小,这样就永远都处于超时状态。可以通过下面公式计算超时监控的时间。 | ||
Supervision Time-out > (Connection Interval) * (1 + [Slave Latency]) | Supervision Time-out > (Connection Interval) * (1 + [Slave Latency]) | ||
行 42: | 行 68: | ||
### 连接参数更新 ### | ### 连接参数更新 ### | ||
- | 连接参数都是主机进行控制,从机并不能直接修改连接参数。但是当主机设置了一组不合适的连接参数,比如主机要求5ms进行一次connect event,但是从机是一个温度计,这样的参数对于从机来说并不合适,所以从机可以发送一个请求,通知主机修改连接参数。但是主机可以选择是否修改当前参数配置,主机可以选择拒绝修改参数。这个过程发生在建立连接之后,所以连接参数的更新可以发生在任意时刻。 | + | |
+ | 连接参数都是主机进行控制,从机并不能直接修改连接参数。但是当主机设置了一组不合适的连接参数,比如主机要求 5ms 进行一次 connect event ,但是从机是一个温度计,这样的参数对于从机来说并不合适。所以从机可以发送一个请求,通知主机修改连接参数,主机可以选择是否修改当前参数配置。 | ||
+ | |||
+ | 这个过程发生在建立连接之后,所以连接参数的更新可以发生在任意时刻。 | ||
```C | ```C | ||
#define DEFAULT_ENABLE_UPDATE_REQUEST | #define DEFAULT_ENABLE_UPDATE_REQUEST | ||
行 51: | 行 81: | ||
#define DEFAULT_CONN_PAUSE_PERIPHERAL 6 | #define DEFAULT_CONN_PAUSE_PERIPHERAL 6 | ||
``` | ``` | ||
- | 在simple_peripheral工程中,我们可以在simple_peripheral.c文件里面找到上面宏定义,这组宏就是设置连接参数。其中DEFAULT_CONN_PAUSE_PERIPHERAL设置一个更新时间(秒为单位),这里设置的6秒,就是建立连接之后6秒外围设备就会发出更新参数请求,通过GAPRole_SendUpdateParam()或 GAPCentralRole_UpdateLink()命令异步发送。也可以更改DEFAULT_ENABLE_UPDATE_REQUEST宏来禁用参数更新,例如# | + | simple_peripheral 工程中可以在 simple_peripheral.c 文件里面找到上面宏定义,这组宏就是设置连接参数。 |
+ | 其中 DEFAULT_CONN_PAUSE_PERIPHERAL 设置一个更新时间(秒为单位),这里设置的 6 秒。即建立连接之后 6 秒外围设备就会发出更新参数请求,通过 GAPRole_SendUpdateParam()或 GAPCentralRole_UpdateLink()命令异步发送。 | ||
+ | |||
+ | 也可以更改 DEFAULT_ENABLE_UPDATE_REQUEST 宏来禁用参数更新,例如 #define DEFAULT_ENABLE_UPDATE_REQUEST | ||
### 连接参数优化 ### | ### 连接参数优化 ### | ||
+ | |||
连接参数直接决定设备的功耗,所以在产品的设计过程中这些参数一定要经过仔细考量,下面给出了连接参数设置的基本策略。 | 连接参数直接决定设备的功耗,所以在产品的设计过程中这些参数一定要经过仔细考量,下面给出了连接参数设置的基本策略。 | ||
行 60: | 行 94: | ||
- 增加两个设备的功耗 | - 增加两个设备的功耗 | ||
- 增加双向吞吐量 | - 增加双向吞吐量 | ||
- | - 减少在任一方向发送数据的时间 | + | - 减少任一方向发送数据的时间 |
增加连接间隔如下: | 增加连接间隔如下: | ||
- 降低两个设备的功耗 | - 降低两个设备的功耗 | ||
- 降低双向吞吐量 | - 降低双向吞吐量 | ||
- | - 增加在任一方向发送数据的时间 | + | - 增加任一方向发送数据的时间 |
减少从机延迟(或将其设置为零)如下: | 减少从机延迟(或将其设置为零)如下: | ||
- 增加外围设备的功耗 | - 增加外围设备的功耗 | ||
- | - 减少外围设备接收从中央设备发送的数据的时间 | + | - 减少外围设备接收从中央设备发送数据的时间 |
增加从机延迟如下: | 增加从机延迟如下: | ||
- 在外围设备没有数据发送到中央设备的期间,可减少外设的功耗 | - 在外围设备没有数据发送到中央设备的期间,可减少外设的功耗 | ||
- | - 增加外围设备接收从中央设备发送的数据的时间 | + | - 增加外围设备接收从中央设备发送数据的时间 |
## 连接终止 ## | ## 连接终止 ## | ||
- | 连接终止的方式有两种,一种是前面提到的超时监控,比如我们设备距离过远的时候,就会发送主机一直收不到从机的响应,一旦超时就会发送连接终止。另一种就是主机或从机由任何原因都可以直接进行连接终止,任何一方发送连接终止的命令,双方就必须终止连接。 | + | |
- | ## GAP抽象层 ## | + | 连接终止的方式有两种,一种是前面提到的超时监控,比如设备距离过远的时候,就会发送主机一直收不到从机的响应,一旦超时就会发送连接终止。另一种就是主机或从机可以直接进行连接终止,任何一方发送连接终止的命令,双方就必须终止连接。 |
- | 如下所示,应用层的绝大部分GAP相关时间都放在了GAPRoleTask进行处理,一部分可以直接调用GAP接口,例如广播和连接设置。 | + | |
+ | ## GAP 抽象层 ## | ||
+ | |||
+ | 如下图 4 所示,应用层的绝大部分 GAP 相关时间都放在了 GAPRoleTask 进行处理。一部分可以直接调用 GAP 接口,例如广播和连接设置。 | ||
![](http:// | ![](http:// | ||
- | 对于GAP事件、数据处理我们尽可能在放在GAPRoleTask,对于一些配置参数我们可以直接调用GAP接口。 | + | |
+ | 图4. GAP 抽象层 | ||
+ | |||
+ | 对于 GAP 事件、数据处理尽可能放在 GAPRoleTask ,对于一些配置参数可以直接调用 GAP 接口。 | ||
## 配置广播参数 ## | ## 配置广播参数 ## | ||
- | GAP层几乎所有功能函数都封装在库文件中,API封装在`gap.h`头文件,绝大部分功能已经在GAPRoleTask通过GAP函数直接调用方式处理,对于广播设置,连接配置这些参数设置我们可以通过通过GAP_SetParamValue()和GAP_GetParamValue()函数进行设置或获取。以下是simple_peripheral_init()中GAP层的配置: | + | |
+ | GAP 层几乎所有功能函数都封装在库文件中,API 封装在 `gap.h` 头文件,绝大部分功能已经在 GAPRoleTask 通过 GAP 函数直接调用方式处理。对于广播设置、连接配置等参数设置可以通过 GAP_SetParamValue()和 GAP_GetParamValue()函数修改。 | ||
+ | |||
+ | 以下是 simple_peripheral_init()中 GAP 层的配置: | ||
````C | ````C | ||
// | // | ||
行 93: | 行 139: | ||
} | } | ||
```` | ```` | ||
- | 上述代码设置了一般广播(General Advertisement)和和限制广播(Limited Advertisement),这里的限制广播的意义是广播启动之后再一定的时间内进行广播,一般我们都是用的Genneral advertisement。代码中两种广播的时间间隔都进行了设置。 | + | |
+ | 上述代码设置了一般广播(General Advertisement)和限制广播(Limited Advertisement)。限制广播的意义是广播启动之后在一定时间内进行广播,一般情况下采用 Genneral advertisement 。代码中两种广播的时间间隔都进行了设置。 | ||
## 加入我们 ## | ## 加入我们 ## | ||
+ | |||
文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | ||
<div> | <div> | ||
行 104: | 行 152: | ||
</ | </ | ||
</ | </ | ||
- |