蓝牙----蓝牙连接建立_连接建立

蓝牙----蓝牙连接建立_连接建立

  • 蓝牙连接建立过程图
  • 1.主机扫描到广播包
    • 1.1判断是否是自己关心的广播包
    • 1.2广播地址添加到扫描列表
  • 2.主机扫描结束,建立连接
  • 3.主从连接成功后,执行连接建立后事件
    • 3.1.主机将连接句柄和设备地址添加到连接列表
    • 3.2.主机进行GATT服务的发现
    • 3.3.从机获取连接句柄,并发起连接参数更新
  • 4.从机发起连接参数更新
    • 4.1主机收到连接参数更新请求
    • 4.2从机进行连接参数更新


蓝牙连接建立过程图

在这里插入图片描述

1.主机扫描到广播包

执行注册的回调函数,触发APP层SC_EVT_ADV_REPORT事件

      //判断广播包是否是自己关心的
      if (SimpleCentral_findSvcUuid(SIMPLEPROFILE_SERV_UUID,
                                    pAdvRpt->pData, pAdvRpt->dataLen))
      {
        //将广播设备的地址和地址类型添加到扫描列表中
        SimpleCentral_addScanInfo(pAdvRpt->addr, pAdvRpt->addrType);
        Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Discovered: %s",
                       Util_convertBdAddr2Str(pAdvRpt->addr));
      }

1.1判断是否是自己关心的广播包

SimpleCentral_findSvcUuid是查看广播包是否包含自己设置的UUID(SIMPLEPROFILE_SERV_UUID)。
广播包的判断有多种也可以对广播数据判断。

从机的广播数据
	static uint8_t advertData[] =
	{
	  0x02,   // length of this data
	  GAP_ADTYPE_FLAGS,
	  DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
	  // service UUID, to notify central devices what services are included
 	 // in this peripheral
 	 0x03,   // length of this data
 	 GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
 	 LO_UINT16(SIMPLEPROFILE_SERV_UUID),
	  HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
主机扫描UUID判断
        if ((adType == GAP_ADTYPE_16BIT_MORE) ||   (adType == GAP_ADTYPE_16BIT_COMPLETE))
        {
          pData++;
          adLen--;
          // For each UUID in list
          while (adLen >= 2 && pData < pEnd)
          {
            // Check for match
            if ((pData[0] == LO_UINT16(uuid)) && (pData[1] == HI_UINT16(uuid)))
            {
              // Match found
              return TRUE;
            }
            // Go to next
            pData += 2;
            adLen -= 2;
          }
        }
 

1.2广播地址添加到扫描列表

SimpleCentral_addScanInfo(pAdvRpt->addr, pAdvRpt->addrType);

//添加一个设备到扫描列表
static void SimpleCentral_addScanInfo(uint8_t *pAddr, uint8_t addrType)
{
  uint8_t i;
  // If result count not at max
  // DEFAULT_MAX_SCAN_RES扫描结果的最大数目
  if (numScanRes < DEFAULT_MAX_SCAN_RES)
  {
    // Check if device is already in scan results
    for (i = 0; i < numScanRes; i++)
    {
      if (memcmp(pAddr, scanList[i].addr , B_ADDR_LEN) == 0)
      {
        return;
      }
    }
    // Add addr to scan result list
    memcpy(scanList[numScanRes].addr, pAddr, B_ADDR_LEN);
    scanList[numScanRes].addrType = addrType;
    // Increment scan result count
    numScanRes++;
  }
}

当到达最大扫描数目时,执行GapScan_disable(),并执行回调函数,触发SC_EVT_SCAN_DISABLED事件

2.主机扫描结束,建立连接

处理SC_EVT_SCAN_DISABLED事件,进行GAP连接

 GapInit_connect(tempMember->addrType & MASK_ADDRTYPE_ID,tempMember->addr, DEFAULT_INIT_PHY, CONNECTION_TIMEOUT);

3.主从连接成功后,执行连接建立后事件

GapInit_connect成功返回GAP层事件GAP_LINK_Estableished,主机及从机进行事件处理

3.1.主机将连接句柄和设备地址添加到连接列表

SimpleCentral_addConnInfo(connHandle, pAddr);

//添加一个设备到 连接列表
static uint8_t SimpleCentral_addConnInfo(uint16_t connHandle, uint8_t *pAddr)
{
  uint8_t i;

  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == CONNHANDLE_INVALID)
    {
      // Found available entry to put a new connection info in
      connList[i].connHandle = connHandle;
      memcpy(connList[i].addr, pAddr, B_ADDR_LEN);
      numConn++;

      break;
    }
  }

  return i;
}

其中connList[]元素结构体定义如下

//连接设备信息
typedef struct
{
  uint16_t connHandle;        // Connection Handle          连接句柄
  uint8_t  addr[B_ADDR_LEN];  // Peer Device Address        连接对端设备地址
  uint8_t  charHandle;        // Characteristic Handle      特征值句柄
  Clock_Struct *pRssiClock;   // pointer to clock struct
} connRec_t;

3.2.主机进行GATT服务的发现

蓝牙----蓝牙消息传输_GATT服务发现

3.3.从机获取连接句柄,并发起连接参数更新

SimplePeripheral_addConn(pPkt->connectionHandle);
从机获取连接句柄,并判断是否到达连接数目,选择继续/停止广播
连接参数更新在自定义的SP_SEND_PARAM_UPDATE_DELAY(6S)后,从机发起

//从机获取连接句柄,进行连接参数更新
static uint8_t SimplePeripheral_addConn(uint16_t connHandle)
{
  uint8_t i;
  uint8_t status = bleNoResources;

  // Try to find an available entry
  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == CONNHANDLE_INVALID)
    {
      // Found available entry to put a new connection info in
      connList[i].connHandle = connHandle;

      // Allocate data to send through clock handler
      connList[i].pParamUpdateEventData = ICall_malloc(sizeof(spClockEventData_t) +
                                                       sizeof (uint16_t));
      if(connList[i].pParamUpdateEventData)
      {
        connList[i].pParamUpdateEventData->event = SP_SEND_PARAM_UPDATE_EVT;
        *((uint16_t *)connList[i].pParamUpdateEventData->data) = connHandle;

        // Create a clock object and start
        connList[i].pUpdateClock
          = (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));
        //启动连接参数更新
        if (connList[i].pUpdateClock)
        {
          Util_constructClock(connList[i].pUpdateClock,
                              SimplePeripheral_clockHandler,
                              SP_SEND_PARAM_UPDATE_DELAY, 0, true,
                              (UArg) (connList[i].pParamUpdateEventData));
        }
        else
        {
            ICall_free(connList[i].pParamUpdateEventData);
        }
      }
      else
      {
        status = bleMemAllocError;
      }

      // Set default PHY to 1M
      connList[i].currPhy = HCI_PHY_1_MBPS;

      break;
    }
  }

  return status;
}

4.从机发起连接参数更新

从机发送连接参数更新GAP_UpdateLinkParamReq

4.1主机收到连接参数更新请求

主机GAP收到GAP_UPDATE_LINK_PARAM_REQ_EVENT连接请求事件,获取新的连接参数,执行连接请求回应GAP_UpdateLinkParamReqReply。

 case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
    {
      gapUpdateLinkParamReqReply_t rsp;
      gapUpdateLinkParamReq_t *pReq;

      pReq = &((gapUpdateLinkParamReqEvent_t *)pMsg)->req;

      rsp.connectionHandle = pReq->connectionHandle;
      rsp.signalIdentifier = pReq->signalIdentifier;
      //允许连接参数更新
      if (acceptParamUpdateReq)
      {
          //收到的 新的连接请求参数
        rsp.intervalMin = pReq->intervalMin;
        rsp.intervalMax = pReq->intervalMax;
        rsp.connLatency = pReq->connLatency;
        rsp.connTimeout = pReq->connTimeout;
        rsp.accepted = TRUE;
      }
      else
      {
        // Reject the request.
        rsp.accepted = FALSE;
      }
      // Send Reply
      // 连接请求回应
      VOID GAP_UpdateLinkParamReqReply(&rsp);
      break;
    }

连接请求回应GAP_UpdateLinkParamReqReply,触发主机的GAP_LINK_PARAM_UPDATE_EVENT事件,对连接参数更新成功与失败情况进行判决。

4.2从机进行连接参数更新

主机向从机连接请求回应GAP_UpdateLinkParamReqReply后,对连接参数更新成功与失败情况进行判决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/356065.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

spring boot学习第八篇:操作elastic search的索引和索引中的数据

前提参考&#xff1a;elastic search入门-CSDN博客 前提说明&#xff1a;已经安装好了elastic search 7.x版本&#xff0c;我的es版本是7.11.1 1、 pom.xml文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns&q…

C++ QT入门1——记事本基础功能实现(基本控件布局+信号与槽+文件类操作)

C QT入门1——记事本基础功能实现&#xff08;基本控件布局信号与槽文件类操作&#xff09; 一、UI界面的基础设置样式表通用配置通过样式表设置按钮三态以图片作为按钮背景 二、按键响应——☆信号与槽信号与槽基本概念按键QPushButton设置信号与槽自定义信号与槽自定义信号与…

【TCP】重传与超时机制

前言 在网络通信的世界里&#xff0c;传输控制协议&#xff08;TCP&#xff09;扮演着一个至关重要的角色。它确保了数据的可靠传输&#xff0c;就像邮差确保每一封信都能准确无误地送达收件人手中一样。但是&#xff0c;网络环境充满了不确定性&#xff0c;数据包可能会因为各…

云堡垒机是软件堡垒机吗?是一种产品吗?

很多小伙伴傻傻分不清楚云堡垒机和软件堡垒机&#xff1f;在问云堡垒机是软件堡垒机吗&#xff1f;是一种产品吗&#xff1f;两者有区别吗&#xff1f;今天我们大家就来一起探讨下&#xff0c;仅供参考哦&#xff01; 首先我们需要知道的是&#xff0c;云堡垒机和软件堡垒机是两…

数字美妆技术:美颜SDK和动态贴纸技术的崭新时代

数字美妆的兴起标志着人们对于自身形象的追求不再局限于现实生活&#xff0c;而是延伸到了虚拟世界。同时&#xff0c;美颜SDK的动态贴纸技术也开始进入到大家的视野之中。 一、美颜SDK&#xff1a;技术之作 通过复杂的图像处理算法&#xff0c;美颜SDK能够实时检测人脸&…

AWS 专题学习 P10 (Databases、 Data Analytics)

文章目录 专题总览1. Databases1.1 选择合适的数据库1.2 数据库类型1.3 AWS 数据库服务概述Amazon RDSAmazon AuroraAmazon ElastiCacheAmazon DynamoDBAmazon S3DocumentDBAmazon NeptuneAmazon Keyspaces (for Apache Cassandra)Amazon QLDBAmazon Timestream 2. Data & …

用java识别出文本中的文字并用in进行拼接

用java识别出来文本&#xff08;txt&#xff09;中的文字&#xff0c;并用in进行拼接。 话不多少&#xff0c;直接上代码。 先看结果 待转换数据&#xff1a; 处理结果&#xff1a; 代码如下&#xff1a; import java.io.*; import java.util.ArrayList; import java.util.Li…

高原涡轮增压20KVA柴油发电机产品样册

高原涡轮增压20KVA柴油发电机产品样册 大泽动力柴油发电机产品品质性能稳定、功率大、维修率好低、能适应各种恶劣环境以及高海拔地区使用&#xff1b; 发电机波形畸变率小于5%&#xff0c;适合给精密设备供电。功率衰减低&#xff0c;机组输出稳定&#xff1b;无励磁绕组&…

毕业找工作只会C语言是不是完蛋了?

今日话题&#xff0c;毕业找工作只会C语言是不是完蛋了&#xff1f;不必担心&#xff0c;C语言是一门非常有价值的编程语言&#xff0c;拥有广泛的应用领域&#xff0c;包括系统编程、嵌入式系统和驱动程序开发&#xff0c;为你提供了多样化的就业机会。学习C语言还有助于深入理…

DjangoURL调度器(一)

一、介绍 当一个用户请求 Django 站点的一个页面&#xff0c;下面是 Django 系统决定执行哪个 Python 代码使用的算法&#xff1a; Django确定要使用的根URLconf模块&#xff0c;一般是在settings中的ROOT_URLCONF设置的值&#xff0c;但是如果传入 HttpRequest 对象具有一个ur…

影响可变利差有几个因素,Anzo Capital昂首资本再说两个

在之前的文章中&#xff0c;Anzo Capital昂首资本抛砖引玉说了影响可变利差的两个因素&#xff0c;后台评论区也是热闹非凡&#xff0c;纷纷留言讨论&#xff0c;攻陷了评论区&#xff0c;今天Anzo Capital昂首资本就把各位投资者的留言进行整理&#xff0c;继续补充影响可变…

航空MRO行业研究:2027年全球市场将达1200亿美元

随着全球航空运输业的不断发展&#xff0c;越来越多的航空器进入了使用年限&#xff0c;需要进行维修、修理和大修。这促进了航空MRO市场的不断增长。此外&#xff0c;航空器设备和技术的不断更新换代&#xff0c;也对航空MRO市场带来了新的机遇和挑战。 航空MRO市场是指维修、…

2024最新版IntelliJ IDEA安装使用指南

2024最新版IntelliJ IDEA安装使用指南 Installation and Usage Guide to the Latest JetBrains IntelliJ IDEA Community Editionn in 2024 By JacksonML JetBrains公司开发的IntelliJ IDEA一经问世&#xff0c;就受到全球Java/Kotlin开发者的热捧。这款集成开发环境&#xf…

vue-admin-template框架

vue-admin-template框架地址&#xff1a;项目地址 项目预览地址&#xff1a;项目预览 框架简介&#xff1a;这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint&#xff0c;这些搭建后台必要的东西。 …

go包与依赖管理

包&#xff08;package&#xff09; 包介绍 Go语言中支持模块化的开发理念&#xff0c;在Go语言中使用包&#xff08;package&#xff09;来支持代码模块化和代码复用。一个包是由一个或多个Go源码文件&#xff08;.go结尾的文件&#xff09;组成&#xff0c;是一种高级的代码…

uniCloud ---- JQL语法 连表查询

目录 JQL数据库操作 JQL流程图解 JQL的限制 单表查询 联表查询 新增 修改 删除 联表查询 例子 字段过滤field 字段别名as 限制查询记录的条数limit 只查一条记录getone JQL数据库操作 JQL&#xff0c;全称 javascript query language&#xff0c;是一种js方式操…

vue3 el-pagination 将组件中英文‘goto’ 修改 为 中文到‘第几’

效果如图&#xff1a; 要求&#xff1a;将英文中Go to 改为到第几 操作如下&#xff1a; <template><div class"paging"><el-config-provider :locale"zhCn"> // 注意&#xff1a;这是重要部分<el-pagination //分页组件根据官…

解锁创意无限:Adobe Photoshop 2023(PS2023)引领设计革命

Adobe Photoshop 2023 (PS2023)&#xff0c;作为图像处理软件的翘楚&#xff0c;以其卓越的性能和无限的可能性&#xff0c;继续引领着数字创意设计的潮流。对于设计师、摄影师、艺术家以及那些对视觉效果有高要求的人们来说&#xff0c;PS2023无疑是他们的必备工具。 在PS202…

OpenHarmony—ArkTS限制throw语句中表达式的类型

规则&#xff1a;arkts-limited-throw 级别&#xff1a;错误 ArkTS只支持抛出Error类或其派生类的实例。禁止抛出其他类型&#xff08;例如number或string&#xff09;的数据。 TypeScript throw 4; throw ; throw new Error();ArkTS throw new Error();限制省略函数返回类…

SpringBoot + Mybatis 快速入门实战

一.创建Spring项目 出现报错的话&#xff0c;换一个jdk创建&#xff0c;一般java 8 选择Spring Web 测试一下 默认端口8080&#xff0c;但是Vue也需要8080&#xff0c;因此&#xff0c;后端设置一个端口3000 再次测试&#xff0c;成功 此处&#xff0c;如何kill一个端口占…