概述
GAP 分层负责设备建立连接的相关功能,包括设备发现、数据链路建立、终止、初始化安全管理和设备配置,参见下图 1 。
图1. GAP 分层的建立连接的示意图
在 Standby
状态,双方设备都处于未连接状态。Advertiser
尝试广播数据,Scanner
接收到广播数据后尝试进行扫描请求,并且得到扫描回复。此时 Scanner
产生连接意图,转变成 Initiator
发送连接请求,成功连接后发送广播的 Advertiser
作为 Master
,进行连接请求的 Initiator
成为 Slave
。
- Standby:复位后设备处于初始空闲状态。
- Advertiser:设备正在通过特定数据进行广告,让任何 Initiator 设备知道它是可一个连接设备(此广告数据负载可以包含设备地址和一些其他数据,如设备名称)。
- Scanner:扫描设备收到广告后,向广告客户发送扫描请求。广播者响应扫描响应。这个过程称为设备发现。当然扫描设备已经知道广告设备可以发起与其的建立连接。
- Initiator:启动时,启动器必须指定要连接的对等设备地址。如果接收到与对等设备地址匹配的广告,则发起设备发送连接请求,该请求包含与广告设备连接所需的连接参数。
- Master/Slave:当连接形成时,广播的发起者作为 Slave ,Initiator 建立者作为 Master。
I. 抓包理解以上连接过程
- Advertiser 进行广播
- Scanner 进行连接请求并且获得回复
- 连接请求
II. 连接参数
连接参数是 Initiator 通过连接请求建立连接时的配置参数。
Connect Interval
蓝牙采用跳频通信,连接的两个设备在某个固定时间切换到某个固定信道进行通信,链路层控制着信道切换。
建立连接后的通信数据被统一定义为 Connection event
。如果没有应用数据发送或者接收,那么链路层也会继续交换数据维护着这个链接。连接间隔是指以 1.25ms
为单位,两次 Connection event
的时间总和。其值可以从 6-3200 ,也就是 7.5ms 到 4.0s 。
图2. 连接间隔
不同的应用需要不同的连接间隔,主要是从功耗进行考虑。
Slave Latency
Slave Latency 可以在没有数据发送的时候选择跳过 connect event 。一个连接事件的发生都是 Master 发送一个通知,设备回复响应然后发送数据。没有数据时假设设置了 Slave Latency = 3 ,那么当 Master 发送通知的时候,Slave可以 3 次不响应,一直保持在深度休眠状态。这样就不会产生 Connect event 事件,从而更加省电。
图3. Slave Latency 的功能示意图
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])
III. 连接参数设置策略
连接参数更新
连接参数都是主机进行控制,从机并不能直接修改连接参数。但是当主机设置了一组不合适的连接参数,比如主机要求 5ms 进行一次 connect event ,但是从机是一个温度计,这样的参数对于从机来说并不合适。所以从机可以发送一个请求,通知主机修改连接参数,主机可以选择是否修改当前参数配置。
这个过程发生在建立连接之后,所以连接参数的更新可以发生在任意时刻。
#define DEFAULT_ENABLE_UPDATE_REQUEST GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 80
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 800
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
#define DEFAULT_DESIRED_CONN_TIMEOUT 1000
#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 宏来禁用参数更新,例如 #define DEFAULT_ENABLE_UPDATE_REQUEST GAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS
连接参数优化
连接参数直接决定设备的功耗,所以在产品的设计过程中这些参数一定要经过仔细考量,下面给出了连接参数设置的基本策略。
减少连接间隔如下:
- 增加两个设备的功耗
- 增加双向吞吐量
- 减少任一方向发送数据的时间
增加连接间隔如下:
- 降低两个设备的功耗
- 降低双向吞吐量
- 增加任一方向发送数据的时间
减少从机延迟(或将其设置为零)如下:
- 增加外围设备的功耗
- 减少外围设备接收从中央设备发送数据的时间
增加从机延迟如下:
- 在外围设备没有数据发送到中央设备的期间,可减少外设的功耗
- 增加外围设备接收从中央设备发送数据的时间
IV. 连接终止
连接终止的方式有两种,一种是前面提到的超时监控,比如设备距离过远的时候,就会发送主机一直收不到从机的响应,一旦超时就会发送连接终止。另一种就是主机或从机可以直接进行连接终止,任何一方发送连接终止的命令,双方就必须终止连接。
V. GAP 抽象层
如下图 4 所示,应用层的绝大部分 GAP 相关时间都放在了 GAPRoleTask 进行处理。一部分可以直接调用 GAP 接口,例如广播和连接设置。
图4. GAP 抽象层
对于 GAP 事件、数据处理尽可能放在 GAPRoleTask ,对于一些配置参数可以直接调用 GAP 接口。
VI. 配置广播参数
GAP 层几乎所有功能函数都封装在库文件中,API 封装在 gap.h
头文件,绝大部分功能已经在 GAPRoleTask 通过 GAP 函数直接调用方式处理。对于广播设置、连接配置等参数设置可以通过 GAP_SetParamValue()和 GAP_GetParamValue()函数修改。
以下是 simple_peripheral_init()中 GAP 层的配置:
//设置广告间隔 {
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL ;
GAP_SetParamValue (TGAP_LIM_DISC_ADV_INT_MIN , advInt );
GAP_SetParamValue (TGAP_LIM_DISC_ADV_INT_MAX , advInt );
GAP_SetParamValue (TGAP_GEN_DISC_ADV_INT_MIN , advInt );
GAP_SetParamValue (TGAP_GEN_DISC_ADV_INT_MAX , advInt );
}
上述代码设置了一般广播(General Advertisement)和限制广播(Limited Advertisement)。限制广播的意义是广播启动之后在一定时间内进行广播,一般情况下采用 Genneral advertisement 。代码中两种广播的时间间隔都进行了设置。
VII. 加入我们
文章所有代码、工具、文档开源。加入我们QQ群 591679055获取更多支持,共同研究CC2640R2F&BLE5.0。
还不快抢沙发