当前位置:   article > 正文

[蓝牙 4.0 CC2541开发] BLE协议栈 GAP GATT_init gap bond manager

init gap bond manager

之前讲系统OSAL浅谈了部分层,这次深入了解一下,BLE多个层之间的关系和沟通方式。

  • BLE 链路建立流程
    – 为什么每次连接蓝牙时间很长
    – 为什么有最大广播间隔,最小广播间隔
    – BLE 怎么省电的!!!
  • GAPRole 蓝牙设备角色建立
  • GAP Bond Manager 连接管理
  • GATT 通用属性配置
    – 什么是特征和属性
    – 什么是服务和协议

BLE 协议栈

GAP: Generic Access Profile

通用访问协议 GAP 主要是做五件事

设备发现;链接建立;链路终止;启动安全功能;设备配置

  • 流程 ↓
  1. 在闲置的时候 Idle :整个蓝牙协议栈并未激活,或正在初始化的空闲状态 Standby
  2. 在设备发现的时候 可以分为两种设备:
    • 广播自身设备地址和一些其他数据的设备
    • 扫描广播的设备,其会收到很多广播,每个被扫描的设备都会回复自己设备地址来响应扫描,反馈其是否可以被连接。
  3. 发起 Initiator:由扫描者发送发起请求,收到对应设备的匹配广播后,扫描者将请求连接。
  4. 连接 Connection:定义发起者是主机 广播者为从机
    在这里插入图片描述
    发起设备也就是主机,在开始连接前会告知广播设备(也就是从机)一些连接参数。

↓ 在应用层的初始化我们可以看到 使用 GAP_SetParamValue 可以设置,还有 GAP_GetParamValue() 可以读取

{//如果要确定一个广播间隔值就将 最大 最小值设为同一个值
    uint16 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 ); //普通可发现模式下设置每次广播的间隔
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

为什么每次连接蓝牙都时间很长?

蓝牙 从机 会在 3 个广播信道中依次广播,而蓝牙 主机 也在3个信道中依次扫描,要两个设备在同一个时间同一个信道扫描到对方并建立连接事件,很多时候需要十几个甚至几十个广播周期。

为什么有最大广播间隔值,最小值广播间隔值?

在广播事件中,LL 层每次广播之前会有会有一个伪随机值的广播延时,防止因为设备之间的时钟不同、上电时间不同,巧合的错开,这种随机广播可以消除这种巧合。

**!BLE省电的关键!,就主要是他不是一直连接的状态,**他会记忆连接状态且进入长时间的休眠!休眠期间芯片可以只达到1.1μA的电流!

参数一般在 GAPRole 任务中处理,主要是连接间隔和从机延迟。

  • 连接事件:两个设备发送和接收数据,一个来回 为 一个连接事件
  • 有效连接间隔:=连接间隔 * (1 + 从机延迟) ****
  • **连接间隔:**约定在多长的时间区间中?再次连接。

如果不设置连接间隔,LL 层将一直维持连接。可以设置以1.25ms/单位的 6(7.5ms) ~ 3200(4s)。最大值必须小于16s的有效连接间隔

如果连接间隔大,则降低功耗,但增加双方发送的时间、减少数据传输速率。反之

  • 从机延迟:一次连接事件后,从机可以几次连接间隔不搭理主机

从机在无数据的时候不再响应主机连接事件,并且关闭射频天线。可以设置0~499个连接事件

如果从机延迟增大,则降低功耗,但增加主机向从机发送的时间,反之

  • 超时断开:很长时间后没有连接事件。

可以设置为以10ms/单位的 10(100ms)~3200(32s)。


当然以上数据双方都是可以在连接后更改的,由 L2CAP层 处理

↓ 初始化部分代码

{
      uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST;
      uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
      uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
      uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY;
      uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT;
      uint8 initial_advertising_enable = TRUE;
        
      // Set the GAP Role Parameters
			//设置 打开关闭广播
      GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable );
			//设置 有限广播模式,广播关闭的时间
      GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );
		  //设置 扫描回复的数据 包括设备名,设备连接间隔,设备发射功率等
      GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );
			//设置 广播的数据 包括设备的发现模式,服务UUID
      GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
		  //设置 从机的连接属性可以更新使能
      GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request );
			//设置 最小连接间隔事件
      GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval );
			//设置 最大连接间隔事件
      GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );
			//设置 从机延迟
      GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency );
			//设置 超时断开
      GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

GAPRole Task

定义蓝牙设备角色建立

因为连接关系配置 GAPRole 占 GAP 比重大,TI把 GAPRole 单独为一个任务,其实 GAPRole 也是 GAP 配置的一部分,将 BLE 底层协议传递给 GAP 和 应用层

GAPRole连接关系配置有哪些连接关系?

广播者:只广播,不能连接

观察者:只扫描,不能连接

外设:可以连接一个链路的广播者

中心:可以连接多个链路的观察者


  • 流程
  1. 应用层初始化 → 应用层事件触发 SBP_START_DEVICE_EVT → 命令 GAP 层设置配置 → 完成 GAPRole 设置
  2. 发送命令 → GAPRole函数 → GAP函数 → BLE 底层返回值 →发送系统消息 GAP_MSG_EVENT → GAPRole接收 → 通知 应用层CB →GAPRole 清空 Msg

GAP Bond Manager

GAP 连接管理。在连接时负责数据和连接安全的,定义经过身份认证后,哪些是可以读的,哪些是可以写的。

一般通过无线发送密钥;使用密钥加密连接;绑定储存密钥;重连使用SNV闪存中的密钥

一般使用 MITM 保护需要创建密码 且需要输入

  • 流程
  1. 应用层初始化 → 应用层事件触发 SBP_START_DEVICE_EVT → 命令 GAP 层设置配置 → 完成 GAPBondMgr 设置
  2. BLE底层 接收到配对请求 → 触发 SYS_EVENT_MSG → GAPBondMgr 接收 → 触发 应用层 CB → GAPBondMgr 清除 Msg
{
    uint16 passkey = 0; // passkey "000000"
    uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
    uint8 mitm = FALSE;
    uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
    uint8 bonding = TRUE;
		// 设置 在MITM模式下 默认密码
    GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey );
		// 设置 配对的模式
    GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode );
		// 设置 MITM保护是否开启
    GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm );
		// 设置 IO 能力
    GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap );
    // 设置 是否请求绑定 默认绑定
		GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding );
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

GATT:Generic Attribute Profile

GATT层 从 应用层 收集信息给 ATT层,ATT层 提供信息给 GATT层 再给 应用层。

通用属性配置。在 GATT 中规定,两个设备连接的时候,他们有两个角色:可以同时充当客户端 服务器

  • Server:服务器有可以让 GATT Client 读写的特征库
  • Client:从服务器读写

什么是特征和属性?

设备之间传输的信息就是属性

特征是安排怎么存储怎么使用属性的描述

一个特征由多个属性构成:特征值、特征声明、特征配置、描述

句柄、类型、权限属性解释其他属性

什么是服务和协议?

多个特征组合在一起是服务,一个到多个服务组合在一起是协议

强制 GAP 服务、强制 GATT 服务:都是底层 BLE 的一部分。每个 BLE 设备都必须声明的。

设备信息、TI示例服务 simpleGATTProfile 是应用层可以定义的。

↓ 在协议里面,是由 句柄 类似指针,UUID 特征值,内部包含的属性的值。

在这里插入图片描述
↓ 看应用层程序对于协议的表

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = 
{
  {   // 服务协议
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* 特征类型 */ // UUID的长度 声明为主服务
    GATT_PERMIT_READ,                         /* 特征的权限 */ // 这里是只读
    0,                                        /* 句柄移动值 */ 
    (uint8 *)&simpleProfileService            /* 特征的值 */ // 属性的值 当前声明主服务的UUID
  },

    { // 服务 声明特征char1
      { ATT_BT_UUID_SIZE, characterUUID },   // UUID长度 声明为声明特征
      GATT_PERMIT_READ,                      // 当前特征为只读
      0,
      &simpleProfileChar1Props               // 声明特征char1的权限 可读可写
    },

      { // Char1的值
        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID }, // UUID长度 声明为特征值
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,         // 当前特征为可读可写
        0, 
        &simpleProfileChar1                           // char1的值
      },
      
      { // char1的描述
        { ATT_BT_UUID_SIZE, charUserDescUUID },       // UUID长度 声明为用户描述
        GATT_PERMIT_READ,                             // 当前特征为只读
        0, 
        simpleProfileChar1UserDesp                    // "Characteristic 1"
      },
		...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

可以看出 原子元素为属性 → 特征 → 服务 → 协议

  • 流程:客户端往服务端写值

初始化 → 应用层使用 GATT_WriteCharValue() → GATT 层 → ATT 层 → BLE底层 → 接受到服务端回复 → 触发系统消息 SYS_EVENT_MSG → 应用层取值

下一次我将利用两套蓝牙设备 完成几个蓝牙特性的实验

公众号已经推进了进度,正在测试蓝牙设备的电池管理模块。

可以关注一波哈

马上回来

在这里插入图片描述

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

闽ICP备14008679号