这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
cc2640r2f:connect_params_update [2017/08/31 16:30] 127.0.0.1 外部编辑 |
cc2640r2f:connect_params_update [2021/06/22 23:14] (当前版本) |
||
---|---|---|---|
行 1: | 行 1: | ||
< | < | ||
- | # BLE连接参数更新过程详解 # | + | # BLE 连接参数更新过程详解 # |
- | 有关连接参数概念和作用我们在 <a href=" | + | 有关连接参数概念和作用在 <a href="http://docs.leconiot.com/doku.php? |
## 介绍 ## | ## 介绍 ## | ||
- | 连接参数更新过程中都是主机发起的,从机只能被动的接收主机设置的参数,这个过程发生在连接的时候,当连接之后如果主机设置的参数不利于从机,从机可以发送请求,请求中包含需要的连接参数,从机请求主机重新更新连接参数,主机可以拒绝,如果主机同意修改连接参数,并且参数合理,则主机发起连接参数更新,如果参数不合理(例如主机不支持过大或者过小的连接间隔),则主机会对参数进行协商,选择最合理的参数进行设置。由于从机发起连接参数更新请求的过程包含了主机发起连接参数更新的过程。本文以simple_peripheral工程为例,演示由从机发起连接参数更新请求的过程。 | + | 连接参数更新过程中都是主机发起的,从机只能被动接收主机设置的参数。 |
+ | |||
+ | 这个过程发生在连接的时候,当连接之后如果主机设置的参数不利于从机,从机可以发送请求,请求中包含需要的连接参数。 | ||
+ | 从机请求主机重新更新连接参数,主机可以拒绝。如果主机同意修改连接参数,并且参数合理,则主机发起连接参数更新。如果参数不合理(例如主机不支持过大或者过小的连接间隔),则主机会对参数进行协商,选择最合理的参数进行设置。 | ||
+ | |||
+ | 从机发起连接参数更新请求的过程包含了主机发起连接参数更新的过程。本文以 simple_peripheral 工程为例,演示由从机发起连接参数更新请求的过程。 | ||
## 硬件环境 ## | ## 硬件环境 ## | ||
- | 使用USB连接< | + | 使用 USB 连接 <a href="http://docs.leconiot.com/doku.php? |
![](http:// | ![](http:// | ||
行 19: | 行 24: | ||
- | 协议栈和IAR安装以及我们工程编译参考< | + | 协议栈和 IAR 安装以及工程编译参考< |
## 运行流程 ## | ## 运行流程 ## | ||
+ | 1. 在 simple_perpheral 中可以选择使用按键和定时器两种方式进行连接参数更新,本文使用定时器的方式进行连接参数更新,并且对定时器启动过程进行分析。 | ||
- | 1. 在simple_perpheral中可以选择使用按键和定时器的方式进行连接参数更新,这里我们使用定时器的方式进行连接参数更新,并且对定时器启动过程进行分析。 | + | 在 peripheral.c 文件中,定义了 `startUpdateClock` 的结构体变量,`startUpdateClock` 作为连接参数更新的定时器事件句柄。 |
- | 在peripheral.c文件中,定义了`startUpdateClock`的结构体变量,`startUpdateClock`作为连接参数更新的定时器事件句柄。在gapRole_init()中,可以找到其初始化过程。**Util_constructClock(& | + | 在 gapRole_init() 中,可以找到其初始化过程:** Util_constructClock (& startUpdateClock, |
- | - 参数1: startUpdateClock表示定时器事件句柄。 | + | - 参数1: startUpdateClock 表示定时器事件句柄。 |
- | - 参数2: gapRole_clockHandler定时事件回调函数。 | + | - 参数2: gapRole_clockHandler 定时事件回调函数。 |
- 参数3: 定时器周期。 | - 参数3: 定时器周期。 | ||
- | - 参数4: 当该参数为0,则定时器执行一次,当该参数不为0,则周期性执行定时,周期值由该值确定。 | + | - 参数4: 当该参数为 0 ,则定时器执行一次,当该参数不为 0 ,则周期性执行定时,周期值由该值确定。 |
- | - 参数5: true表示立即执行,false表示等待。 | + | - 参数5: true 表示立即执行,false 表示等待。 |
- 参数6: 定时器回调参数。 | - 参数6: 定时器回调参数。 | ||
- | 所以这里创建了一个周期为0,并且只执行一次的定时器,其中回调处理函数的参数是START_CONN_UPDATE_EVT事件。 | ||
- | 2.在`gapRole_processGAPMsg`中,`GAP_LINK_ESTABLISHED_EVENT`事件的处理过程里面可以看见 | + | 这里创建了一个周期为 0 ,并且只执行一次的定时器,其中回调处理函数的参数是 START_CONN_UPDATE_EVT 事件。 |
+ | |||
+ | 2. 在 `gapRole_processGAPMsg` 中,`GAP_LINK_ESTABLISHED_EVENT` 事件的处理过程可以看到: | ||
````C | ````C | ||
// | // | ||
行 40: | 行 48: | ||
Util_restartClock(& | Util_restartClock(& | ||
```` | ```` | ||
- | 所以当一旦连接建立,就启动该定时器,这里`timeout`通过`GAP_GetParamValue`得到。在`SimpleBLEPeripheral_init`函数中,通过下面代码段已经设置了DEFAULT_CONN_PAUSE_PERIPHERAL值。 | + | 一旦连接建立,就启动该定时器。`timeout` 通过 `GAP_GetParamValue` 得到。在 `SimpleBLEPeripheral_init` 函数中,下面代码段已经设置了DEFAULT_CONN_PAUSE_PERIPHERAL 值。 |
````C | ````C | ||
// | // | ||
行 47: | 行 55: | ||
GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, | GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, | ||
```` | ```` | ||
- | 当定时器时间到达后,调用下面回调函数,并传入初始化中设置的`START_CONN_UPDATE_EVT`参数,可以看出,该回调函数仅发送了一个事件。 | + | 当定时器时间到达后,调用下面的回调函数,并传入初始化中设置的 `START_CONN_UPDATE_EVT` 参数,可以看出该回调函数仅发送了一个事件。 |
````C | ````C | ||
// | // | ||
行 55: | 行 63: | ||
} | } | ||
````` | ````` | ||
- | 然后在`gapRole_taskFxn`函数中进行相应事件处理。这里调用`gapRole_startConnUpdate`函数进行连接参数更新。 | + | 然后在 `gapRole_taskFxn` 函数中进行相应事件处理,调用 `gapRole_startConnUpdate`函数进行连接参数更新。 |
````C | ````C | ||
// | // | ||
行 65: | 行 73: | ||
```` | ```` | ||
- | 而在simple_peripheral.c中使用以下函数端对连接参数变量进行赋值。其中需要特别注意`DEFAULT_ENABLE_UPDATE_REQUEST`。需要在其 定义处修改成`GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS`。这样双方都可以启动连接参数更新过程。 | + | 最后在 simple_peripheral.c 中使用以下函数端对连接参数变量进行赋值。特别注意 `DEFAULT_ENABLE_UPDATE_REQUEST` |
````C | ````C | ||
// | // | ||
行 74: | 行 83: | ||
uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; | uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; | ||
```` | ```` | ||
- | 3. 上述过程理解清楚后,我们就可以在`peripheral.c`文件中直接修改连接参数,在更新的时候使用我们自己设置的连接参数。 | + | 3. 上述过程理解清楚后,就可以在 `peripheral.c` 文件中直接修改连接参数,在更新的时候使用自己设置的连接参数。 |
````C | ````C | ||
// | // | ||
行 82: | 行 92: | ||
```` | ```` | ||
- | 下图是使用BTool建立连接之后等待6秒收到的数据。可以看出在连接的时候使用的是主机端设置的连接参数。ConnInterval=80,ConnLatency=0,ConnTimout=2000。建立连接6秒之后,启动连接参数更新,并且更新为设置的 ConnInterval=500,ConnLatency=1,ConnTimout=2500。 | + | 下图是使用 BTool 建立连接之后等待 6 秒收到的数据。可以看出,在连接的时候使用的是主机端设置的连接参数。ConnInterval = 80 ,ConnLatency = 0 ,ConnTimout = 2000 。建立连接 6 秒之后,启动连接参数更新,并且更新为设置的 ConnInterval = 500 ,ConnLatency = 1 ,ConnTimout = 2500 。 |
![](http:// | ![](http:// | ||
- | 下面我们使用Packet Sniffer抓包分析一下流程:如图示首先定时器时间到达之后,由从机向主机(S-> | + | 使用 Packet Sniffer 抓包分析一下流程: |
+ | 如图所示,首先,定时器时间到达之后,由从机向主机(S-> | ||
+ | 然后,主机端会根据从机的参数进行一次协商,如果从机设置的参数不满足主机端设置的最大值或最小值,则主机会设置当前支持的最大值。举个例子,如果把 `DEFAULT_DESIRED_CONN_TIMEOUT` 改成一个比较小的数值,主机端可能就不会使用我们设定的值,而使用主机端所能支持的最小值。 | ||
+ | 最后,主机发送协商之后最终使用的连接参数(M-> | ||
```C | ```C | ||
// | // | ||
行 93: | 行 108: | ||
#define L2CAP_CONN_PARAMS_REJECTED | #define L2CAP_CONN_PARAMS_REJECTED | ||
``` | ``` | ||
+ | |||
![](http:// | ![](http:// | ||
下面是连接过程中,由主机直接发起的连接参数更新请求,可以看出如果是主机直接修改连接参数,只需要发送连接参数更新请求。从机返回响应之后即完成了连接参数更新。 | 下面是连接过程中,由主机直接发起的连接参数更新请求,可以看出如果是主机直接修改连接参数,只需要发送连接参数更新请求。从机返回响应之后即完成了连接参数更新。 | ||
+ | |||
![](http:// | ![](http:// | ||