当前位置: 首页 > news >正文

CH579 CH573 CH582 CH592 蓝牙主机(Central)实例应用讲解

蓝牙主机(Central),顾名思义,就是一个蓝牙主设备,与从机(Peripheral)建立连接进行通信,可以接收从机通知,也可以给从机发送信息,通常Central和Peripheral结合使用。

一、官方例程Central的工作流程

从官方例程中,我们可以看到,Central的工作流程大致如下:

一、初始化完成开启扫描,

二、获取扫描信息

三、将扫描到的mac地址与目标连接mac地址作比较,扫描到目标mac就发起连接否则继续开启扫描

四、枚举服务进行通信测试

上图标注1:开始扫描
标注2将扫描获取的从机MAC地址加入扫描列表
标注3与目标连接MAC地址比较
标注4没有找到目标,重新开始扫描
标注5找到目标mac,发起连接

从上述描述中我们知道,要想与Peripheral建立连接,必须知道Peripheral的MAC地址,但实际应用中,我们很难知道Peripheral的MAC的地址,就算知道了,也很难输入Central中,毕竟大多数情况下,每个Peripheral的MAC地址是不同的,尤其是我们针对的是现有的产品时。

那么我们如何应对这种问题呢?

二、BLE广播数据中的AD Type详解

 一般来说,同一种产品,广播数据是相同的,甚至同一个厂家的同一种类型的产品,广播数据也会有一些共同的特征,我们可以通过研究产品的广播数据来解决上面提到的问题。所以我们先来了解一下广播数据中的AD Type。

AD Type是广播数据单元(AD Structure)的核心字段,用于定义后续数据(AD Data)的类型和格式。以下是常见AD Type的分类及说明:

一)、基础设备信息类

  1. Flags(类型=0x01)

    • 功能‌:标识设备的发现模式和兼容性,如是否支持BLE/BR/EDR双模。
    • 数据格式‌:1字节,各bit位含义:
      • Bit 0:LE有限发现模式(仅临时可连接)
      • Bit 1:LE普通发现模式(持续可连接)
      • Bit 2:不支持BR/EDR(纯BLE设备)
      • Bit 3-4:控制器/主机支持双模
    • 示例‌:0x06表示支持普通发现模式且不支持BR/EDR。
  2. 完整设备名称(类型=0x09)

    • 功能‌:声明设备完整名称(如Nordic_HRM)。
    • 数据格式‌:UTF-8字符串,长度由Len字段定义。
  3. 缩短设备名称(类型=0x08)

    • 功能‌:设备名称的缩写形式,用于节省广播数据空间。

二)、服务声明类

  1. 完整16位服务UUID列表(类型=0x03)

    • 功能‌:广播设备支持的所有16位标准服务UUID(如心率服务0x180D)。
    • 数据格式‌:多个2字节UUID连续排列。
  2. 非完整服务UUID列表(类型=0x02)

    • 功能‌:仅声明部分服务,需通过扫描响应或连接后获取完整列表。
  3. 32位/128位服务UUID(类型=0x04-0x07)

    • 功能‌:声明长格式服务UUID(如自定义服务)。

三)、设备能力与参数类

  1. 发射功率等级(类型=0x0A)

    • 功能‌:广播设备的发射功率值(单位dBm),用于距离估算。
    • 数据格式‌:1字节有符号整数(如0xF6表示-10 dBm)。
  2. 设备类别(类型=0x0D)

    • 功能‌:标识设备类型(如手机、传感器)。
    • 数据格式‌:3字节,按蓝牙标准分类编码。

四)、厂商自定义数据类

  • 厂商特定数据(类型=0xFF)
    • 功能‌:携带厂商自定义数据(如iBeacon、Eddystone协议)。
    • 数据格式‌:前2字节为厂商ID(如苹果为0x004C),后续为自定义内容。

五)、其他类型

  • 可连接间隔(类型=0x12)‌:声明设备建议的连接参数。
  • 服务请求(类型=0x14)‌:主动请求特定服务(如定位服务)。
  • 还有更多AD Type,这里就不细说,毕竟与我们的主题关系不大,有兴趣的朋友可以很容易从网上搜索到相关的解释。

六)、关键限制与注意事项

  1. 数据长度限制‌:单个广播包载荷(Payload)总长度不超过31字节。
  2. 组合使用‌:一个广播包可包含多个AD Structure,需合理分配类型优先级(如优先Flags和服务声明)。
  3. 动态更新‌:部分AD Type(如设备名称)支持动态修改以适应场景需求。
  4. 以上AD Type并非全部必需,可以根据产品的特性及实际需要来提供。

 三、实例讲解

根据”BLE广播数据中的AD Type详解“一节所述,以及上面三张广播包图,我们很容易知道,广播包包含的内容比较随意,没有强制要求,但AD Type 0x09,也就是设备名称通常会包含,所以蓝牙主机(Central)在扫描时,可以根据AD Type 0x09来判断是否是目标连接。当然我们根据广播包的信息,很容易知道,可以用AD Type 0x07(自定议服务UUID)或用AD TypxFF(厂家自定义的数据类型)来判断是否是目标连接。

接下来,我们以佳能相机蓝牙遥控器为例来讲解如何根据AD Type 0x09及AD Type 0x07来判断是否是目标连接,如果是,则发起连接请求。(因为该项目是商用项目,我们没办法所完整的源码上传,所以只会贴一部分与本主题有关的代码)。

#define PAIR_MODE_TYPE 0x07const uint8_t Serv_uuid[ATT_UUID_SIZE] = {0x21,0xa8,0xff,0x2f,0x49,0xd8,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x05,0x00};const uint8_t cannon_EOSM50[DEVICE_NAME_MAX_LEN] = {0x45,0x4F,0x53,'M',0x35,0x30,0,0,0,0,0,0,0,0,0,0};
const uint8_t cannon_EOS800D[DEVICE_NAME_MAX_LEN] = {0x45,0x4F,0x53,0x38,0x30,0x30,0x44,0,0,0,0,0,0,0,0,0};
const uint8_t cannon_SX70[DEVICE_NAME_MAX_LEN] = {0x53,0x78,0x37,0x30,0,0,0,0,0,0,0,0,0,0,0,0};
const uint8_t * Device_List[DEVICE_COUNT] = {cannon_EOSM50,cannon_EOS800D,cannon_SX70};case GAP_DEVICE_INFO_EVENT:{// Add device to list
//            centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);if (IsPaired)break;uint8_t cmystata;uint8_t UserNamelen,len;uint8_t EvtData[31];#ifdef DEBUGsprintf(EvtData,"%s",pEvent->deviceInfo.pEvtData);    //将扫描的数据格式化成字符串进行子字符串匹配
#endif//以下为字符串匹配for (uint8_t i = 0; i < pEvent->deviceInfo.dataLen;){if(pEvent->deviceInfo.pEvtData[i]>=2){len = pEvent->deviceInfo.pEvtData[i];if(pEvent->deviceInfo.pEvtData[i+1] == PAIR_MODE_TYPE){
#if 0for (uint8_t idx = 0; idx < DEVICE_COUNT; idx ++){cmystata = tmos_memcmp(&pEvent->deviceInfo.pEvtData[i+2],Device_List[idx],len-1);if (cmystata == TRUE){
//                    Device_Ctrl.Device_Idx = idx;break;}}
#elsecmystata = tmos_memcmp(&pEvent->deviceInfo.pEvtData[i+2],Serv_uuid,len-1);
#endifif(cmystata == TRUE) //  找到了{
//                StrMatchingFlag = TRUE;GAPRole_CentralCancelDiscovery();     //取消设备扫描发现centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);}PRINT("\r\n");return;}else{i += len+1;}}else{i++;}}}break;case GAP_DEVICE_DISCOVERY_EVENT:{PRINT("Device found...\n");GAPRole_CentralEstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,DEFAULT_LINK_WHITE_LIST,centralDevList[0].addrType,centralDevList[0].addr);//                BLEConnected = BLE_CONNECTING;// Start establish link timeout eventtmos_start_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT, ESTABLISH_LINK_TIMEOUT);PRINT("Connecting...\n");}break;

以上代码,简单阐述一下,本来我们开始是打算根据AD Type 0x09(也就是设备名称)来判断是否是目标连接,但后来客户不断的增加相机类型,甚至还要求支持没有提供的设备,所以转为根据AD Type 0x07(自定议服务UUID)来判断。

#define PAIR_MODE_TYPE 0x07就是指AD Type 0x07,如果要根据AD Type 0x09,这个地方需要修改,程序代码可能也需要略作修改,毕竟我们后面的代码全部是根据AD Type 0x07(自定议服务UUID)来开发的。

代码本身比较简单,与官方例程不同的是, case GAP_DEVICE_INFO_EVENT:官方例程只是把扫描到的信息添加到相应的列表中, case GAP_DEVICE_DISCOVERY_EVENT: 在这里才判断是否是目标连接。而我们的实例则是在case GAP_DEVICE_INFO_EVENT:就判断是否是目标连接,而在case GAP_DEVICE_DISCOVERY_EVENT: 只是简单的发起连接请求。

相关文章:

  • 生产级AI/ML特征存储平台:Feast全面使用指南 — Use Cases Third party integrations FAQ
  • TransmittableThreadLocal:穿透线程边界的上下文传递艺术
  • PostgreSQL 的 pg_advisory_lock_shared 函数
  • 机器学习 day01
  • 【金仓数据库征文】金融行业中的国产化数据库替代应用实践
  • 抖音视频上传功能测试全维度拆解——从基础功能到隐藏缺陷的深度挖掘
  • 【25软考网工】第六章(2)信息加密技术
  • 机器视觉光源的特点及选择应用
  • springboot3+vue3融合项目实战-大事件文章管理系统-更新用户信息
  • [亲测搭建可用]LoliMeow主题二次元风博客WordPress主题模板
  • 基于GF域的多进制QC-LDPC误码率matlab仿真,译码采用EMS算法
  • Go语言超时控制方案全解析:基于goroutine的优雅实现
  • [面试]SoC验证工程师面试常见问题(七)低速接口篇
  • Webug4.0靶场通关笔记-靶场搭建方法(3种方法)
  • 【Oracle认证】MySQL 8.0 OCP 认证考试英文版(MySQL30 周年版)
  • 通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志
  • 《自动驾驶封闭测试场地建设技术要求》 GB/T 43119-2023——解读
  • 简易图片编辑工具,支持抠图和替换背景
  • WordPress插件targetsms存在远程命令执行漏洞(CVE-2025-3776)
  • 2.商户查询缓存
  • 种罂粟喂鸡防病?四川广元一村民非法种植毒品原植物被罚​
  • 云南多地突查公职人员违规饮酒:公安局门口开展酒精吹气测试
  • 解放军仪仗分队参加白俄罗斯纪念苏联伟大卫国战争胜利80周年阅兵活动
  • 华泰柏瑞基金总经理韩勇因工作调整卸任,董事长贾波代为履职
  • 马上评|让“贾宝玉是长子长孙”争议回归理性讨论
  • 新华每日电讯:给“男性妇科病论文”开一剂复方药