https://blog.csdn.net/z497544849/article/details/84143224
在解析蓝牙的sniff mode之前,我们先来回顾一下蓝牙有哪些连接状态。
一、 蓝牙的连接状态转换图如下:
http://blog.chinaunix.net/attachment/201605/6/21411227_1462520395149C.png
Connection State:如上图所示,蓝牙的连接态有几个子状态,分别如下:
其中包含三种状态属于节能态,Sniff/Hold/Park Mode.
Connectionless Slave Broadcast Mode:
用来传输特性广播数据(profile broadcast data)。
Active Mode:(主动模式)
在此模式下,微微网内部所有的从设备都可以和主设备通信,当然按照Spec最多只能有七个从设备。所有的通信都有主设备来主导。微微网所有的从设备都会在主设备-> 从设备时隙上监听数据包。如果一个从设备没有被寻址,它将等待下一个数据传输。从设备能从主设备传输的包头获取传输占用的时隙,在此期间没有被寻址的设备将会等待传输时隙。具体可以参考下图,多从设备传输时序图:
http://blog.chinaunix.net/attachment/201605/6/21411227_1462520423hUQF.png
Sniff Mode:(呼吸模式)
呼吸模式通过减少主设备发送数据的时隙数并相应减少从设备监听的时隙数,从而达到节省电源的目的。在sniff模式下主设备将每隔Tsniff向从设备发送数据包,所以从设备每隔Tsniff去监听主设备的数据包即可!slave就是只在sniff anchor point时监听。sniff mode只能应用于异步传输,不能应用于同步逻辑传输。后面会详细介绍这部分。
Hold Mode:
保持模式是蓝牙节能模式中最简单的一种。主从设备将对从设备处于保持模式的时间进行协商 ,一旦连接处于保持模式,此连接就不再支持数据包,从而可以节省电源或参与到其它微微网(piconet)中。有一点非常重要,即当每次进入保持模式时都需要对保持周期进行协商。关于保持模式还有一个更加重要的方面,即一旦设备进入保持模式就不能取消,并且保持周期必须在通信恢复前结束。
从机和主机协商一个保持时间,在此期间从设备进入低功耗模式但仍然保持LT_ADDR。异步传输在此模式下,不响应当然微微网的任何数据包。但在同步传输模式下(SCO,eSCO)需要支持保留时隙的数据包。在此模式下的设备可以scanning, paging, inquiring, 或者加入其它的微微网。
Park State:
暂停模式可以最大限度的节省电源。当一个从设备不需要一直参与微微网的信道,但是却需要保持跟信道的同步时,从设备可以进入Park state。
处于Park state状态下的从设备只有很少的活动,它会选择放弃它的逻辑传输地址 LT_ADDR,取而代之的是,它会使用两个新的地址:
PM_ADDR: 8-bit Parked Member Address
AR_ADDR: 8-bit Access Request Address
另外,为了达到低功耗的目的,在Park state下,一个master可以连接多于七个slaves. 在一时刻, 只有七个slaves可以开始连接状态。但是,通过交换active slave 和park slave, 在微微网中的slaves的数目可以达到更多(255 如果PM_ADDR被使用的时候,并且如果用了BD_ADDR,这个数目还可以随机大);
二、sniff mode及其参数的解释
sniff mode干什么用的?
简单来说,他就是为了省电用的。在active mode,slave必须在每个master-to-slave的slot中监听master的数据,看看有没有发给自己的;而一旦进入sniff mode,slave就不必每个master-to-slave slot都去监听。这样slave就可以更加省电了,没事儿的时候就可以睡下去。但是它必须定期醒过来,看看master是否有消息传过来。
sniff mode的基本概念
https://img-blog.csdn.net/20150215183400065?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
上面这张图说的就是前面讲得sniff mode。
首先是sniff interval,也就是slave定期(醒来)监听master数据的时间周期。图中用Tsniff来表示这个参数。其实它是以slot为单位的,具体的周期还得乘以0.625ms。假如某个slave请求的sniff mode的interval为18个slot,则它的Tsniff为18,周期为18*0.625=11.25ms。
其次是sniff anchor point,也就是所谓的sniff锚点。从这个锚点开始,slave会监听一段时间master的报文(从而锚点必然是某个master-to-slave slot的开始)。如果没有消息,那么slave可能就要休息去了。具体slave监听多久,有几个参数来决定。Wait,我们等会再讨论它们。上面这张图说的是一个slave的情况,那要是有多个slave怎么办呢?看下面这张图:
https://img-blog.csdn.net/20150215190226692?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
此图说明了多个slave的情况。当遇到多个slave请求进入sniff mode时,slave必须在sniff interval的基础上通过设置一个偏移量来决定自己实际的anchor point。这一点是通过下面这个等式来实现的:
Dsniff = Clock_Value (bits 26-1) mod Tsniff
这里的Dsniff就是前面提到的offset。它必须为偶数,因为master只会在偶数slot给slave发包。slave在请求进入sniff mode时,通过Dsniff这个参数就可以与其他处在sniff mode的设备区分开,获得不同时间的anchor point。(有没有觉得以上的两张图风格不一样?前一个是core spec的,后一个则是whitepaper中的)。
下面来看看剩下的两个参数——Nsniff_attempt和Nsniff_timeout。先说说Nsniff attempt,它表示slave在每个sniff interval中监听master-to-slave的slot数量。下图说明了Nsniff_attempts为3的情况,slave必须在anchor point到来后的3个slot内保持监听状态。
https://img-blog.csdn.net/20150215191813317?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
几点说明:
1)由于master-to-slave和slave-to-master的slot是交叉出现的,因此图中Nsniff_attempt的持续时间为3+2=5个slot,包含3个master-to-slave slot;
2)由于包含anchor point开始的第一个slot,因此Nsniff_attempt的值必须至少为1;
3)Nsniff_attempt的最大不得超过Tsniff/2;
4)在Nsniff_attempt中的每个master-to-slave slot,slave都必须处在监听状态;
5)如果在Nsniff_attempt期间slave没有收到master的数据,那么slave就可以睡下去了。
最后一个参数是Nsniff_timeout,它的作用在下图得到了较好的说明:
https://img-blog.csdn.net/20150215192927114?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXRhZGFsaWdodA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
在上面这张图中,如果在Nsniff_attempt期间收到master的数据,那么slave还必须继续继续监听Nsniff_timeout数量的master-to-slave slot,以便两者继续交换data而不用等到下一个anchor point到来。注意,一旦收到数据,slave就必须重新等待Nsniff_timeout个slot,这个值不会改变。
---------------------
作者:no输给现实
来源:CSDN
原文:https://blog.csdn.net/z497544849/article/details/84143224
版权声明:本文为博主原创文章,转载请附上博文链接!