当前位置:   article > 正文

蓝牙的数据交互流程_蓝牙协议栈交互

蓝牙协议栈交互

上篇:蓝牙的概述中介绍了,蓝牙协议的架构。其实协议就是一种包装规则,两个设备使用蓝牙协议进行通信,那么发出的数据就要经过蓝牙协议规则的包装,最后才能发出去,对方根据协议解包装,得到数据。

1.广播方式

对象:advertiser(广播者),scanner或者observer(扫描者)。手机蓝牙连接耳机蓝牙,手机是扫描者,蓝牙耳机是广播者。手机蓝牙上面可以扫描到很多的蓝牙设备。广播通信流程如下:广播者send(0x64)

  • 第一步:GAP层,定义数据的含义,0x64这个数据是表示什么的数据是湿度还是电量,还是其他的。GAP层引入了LTV(Length-Type-Value)结构来定义数据,比如020105,02-长度,01-类型(强制字段,表示广播flag,广播包必须包含该字段),05-值。由于广播包最大只能为31个字节,它能定义的数据类型极其有限,像这里说的电量,GAP就没有定义,因此要通过广播方式把电量数据发出去,只能使用供应商自定义数据类型0xFF,即04FF590064,其中04表示长度,FF表示数据类型(自定义数据),0x0059是供应商ID(自定义数据中的强制字段),0x64就是我们的数据(设备双方约定0x53就是表示电量,而不是其他意思)。数据变成:02010504FF590064
  • 第二步:LL层. 添加access address概念,用来指明接收者身份,其中,D6BE898E 这个access address比较特殊,它表示要发给周边所有设备,即广播。再加上 LL帧头字段, 有效数据包长度,广播者的地址,CRC
  • 最终结果:AAD6BE898E600E3B75AB2A02E102010504FF5900648EC7B2
    • AA – 前导帧(preamble)
    • D6BE898E – 访问地址(access address)
    • 60 – LL帧头字段(LL header)
    • 0E – 有效数据包长度(payload length)
    • 3B75AB2A02E1 – 广播者设备地址(advertiser address)
    • 02010504FF590064 – 广播数据
    • 8EC7B2 – CRC24值

    缺点

  •   无法进行一对一双向通信 (广播是一对多通信,而且是单方向的通信)
  • 由于不支持组包和拆包,因此无法传输大数据
  • 通信不可靠及效率低下。广播信道不能太多,否则将导致扫描端效率低下。为此,BLE只使用37(2402MHz) /38(2426MHz) /39(2480MHz)三个信道进行广播和扫描,因此广播不支持跳频。由于广播是一对多的,所以广播也无法支持ACK。这些都使广播通信变得不可靠。
  • 扫描端功耗高。由于扫描端不知道设备端何时广播,也不知道设备端选用哪个频道进行广播,扫描端只能拉长扫描窗口时间,并同时对37/38/39三个通道进行扫描,这样功耗就会比较高。

2.连接方式

        设备A和设备B建立蓝牙连接,就是指设备A和设备B两者一对一“同步”成功.建立成功的条件如下:

  • 设备A和设备B对接下来要使用的物理信道达成一致
  • 设备A和设备B双方建立一个共同的时间锚点,也就是说,把双方的时间原点变成同一个点
  • 设备A和设备B两者时钟同步成功,即双方都知道对方什么时候发送数据包什么时候接收数据包
  • 连接成功后,设备A和设备B通信流程如下所示:

 如上图,当设备A和设备B,再同一时钟内TX和RX是一一对应的。

现在我们看看连接状态下是如何把数据0x53发送出去的,从中大家可以体会到蓝牙协议栈分层的妙处。

  • 对开发者来说,很简单,他只需要调用send(0x53)
  • GATT层定义数据的类型和分组,方便起见,我们用0x0013表示电量这种数据类型,这样GATT层把数据打包成130053(小端模式!)
  • ATT层用来选择具体的通信命令,比如读/写/notify/indicate等,这里选择notify命令0x1B,这样数据包变成了:1B130053
  • L2CAP用来指定connection interval(连接间隔),比如每10ms同步一次(CI不体现在数据包中),同时指定逻辑通道编号0004(表示ATT命令),最后把ATT数据长度0x0004加在包头,这样数据就变为:040004001B130053
  • LL层要做的工作很多,首先LL层需要指定用哪个物理信道进行传输(物理信道不体现在数据包中),然后再给此连接分配一个Access address(0x50655DAB)以标识此连接只为设备A和设备B直连服务,然后加上LL header和payload length字段,LL header标识此packet为数据packet,而不是control packet等,payload length为整个L2CAP字段的长度,最后加上CRC24字段,以保证整个packet的数据完整性,所以数据包最后变成:
    • AAAB5D65501E08040004001B130053D550F6
      • AA – 前导帧(preamble)
      • 0x50655DAB – 访问地址(access address)
      • 1E – LL帧头字段(LL header)
      • 08 – 有效数据包长度(payload length)
      • 04000400 – ATT数据长度,以及L2CAP通道编号
      • 1B – notify command
      • 0x0013 – 电量数据handle
      • 0x53 – 真正要发送的电量数据
      • 0xF650D5 – CRC24值
      • 虽然开发者只调用了 send(0x53),但由于低功耗蓝牙协议栈层层打包,最后空中实际传输的数据将变成下图所示的模样,这就既满足了低功耗蓝牙通信的需求,又让用户API变得简单,可谓一箭双雕!

参考链接: 深入浅出低功耗蓝牙(BLE)协议栈 - iini - 博客园

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/691044
推荐阅读
相关标签
  

闽ICP备14008679号