蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)蓝牙配对和绑定蓝牙 4 0BLE 信道 RFChannel BLE 协议栈分层 PHY 层 Physicallaye 物理层 LL 层 LinkLayer 链路层 HCI 层 Hostcontroll

大家好,欢迎来到IT知识分享网。

目录

蓝牙配对和绑定

https://www.cnblogs.com/iini/p/12801242.html

蓝牙4.0 BLE

BLE全称Bluetooth Low Energy,低功耗蓝牙,是一种无线传输小数据的超低功耗蓝牙技术。蓝牙设备总共分为三种:Bluetooth、Bluetooth smart、Bluetooth smart ready。

  • Bluetooth设备是经典蓝牙设备(比如蓝牙耳机),包括BR/EDR/AMP三种技术;
  • Bluetooth smart是BLE设备(比如蓝牙温度计),即低功耗蓝牙设备;
  • Bluetooth smart ready是双模蓝牙设备(比如手机),即同时支持传统蓝牙和低功耗蓝牙。

这三种设备的区别和联系如下图(箭头表示可以连接):

在这里插入图片描述

在这里插入图片描述

新蓝牙技术标准推动了IPv6协议引入蓝牙标准的进程,蓝牙4.2标准设备可以直接通过IPv6和6LoWPAN接入互联网。

既然是无线芯片呢,其组成由软件和硬件构成。

  • 软件部分,为 BLE 协议栈
  • 硬件部分包含 RF PHY(无线收发装置),Modem(调制解调器),以及 Baseband(基带)构成。

BLE 的协议规范,全部需要遵循 Core Spec 来进行定制,Core Spec 中包含了 RF 、Modem、Air Interface,数据编码/解码,以及软件的协议规范

信道(RF Channel)

摘自:BLE(2)——基本特性(状态、角色、地址、信道)

蓝牙 BLE 工作在 2.4GHz 的频段上,分为 40 个 RF 信道,每个信道 2M。同一时刻,只能用一个信道进行数据的传输/接收。

物理信道从 0 – 39 进行编号。Index广播信道:PHY Ch0 对应 37,PHY Ch12 对应 38,PHY 39 对应 39。

在这里插入图片描述
在 BLE 4.2 时代,Advertising、Scanning、Initiating 状态只允许在 Ch Index 的 37/38/39 上执行数据的收发。Advertising 是为了让其他 BLE 设备发现本设备,Scanning 是为了扫描到其他设备。为了让发现设备和广播更容易不受诸如 WIFI 的干扰,专门将 Advertising、Scanning、Initiating 数据收发放到了 与 WIFI 频段隔离的部分,起到一定抗干扰作用:
在这里插入图片描述

除了 37、38、39 这些频段,在 Connection 状态下使用了 其他的 37 个 Channel通信信道,通过跳频技术(Hopping),来减少数据干扰,增强系统的可靠性。

BLE协议栈分层

  • 协议:类似语言,如汉语、英语等。所谓协议,即将指定的字节按照一定的顺序排列起来,以便他人使用自己的设备时,能通过该协议同其他设备进行通信。协议的特点,就是有固定的帧格式,通过该格式发送,接收者通过解读帧格式,进而得到新息内容;
  • 协议栈:协议的具体实现形式,通俗可理解为代码的实现、函数库,供开发人员调用;
  • BLE协议栈:将蓝牙各个层的协议集合在一起,以函数库的形式体现,并提供应用层的API供用户调用。

下图是协议栈的结构分层:

在这里插入图片描述

在这里插入图片描述

PHY层(Physical layer 物理层)

PHY层用来指定BLE所用的无线频段(2.4G),调制解调方式和方法、跳频等。PHY层做得好不好,直接决定整个BLE芯片的功耗,灵敏度以及selectivity等射频指标。

LL层(Link Layer 链路层)

主要是RF射频控制,链路层定义了协议栈中最为基础的状态机、数据包格式、广播和连接流程等问题

LL层的五种RF射频状态:

  • Standby 待机状态
  • Advertising 广播状态
  • Scaning 扫描状态
  • Initiating 发起连接状态
  • Connected 连接状态

HCI层(Host controller interface 主机控制接口层)

HCI 层通信层,host 和 controller 提供一个标准化的传输接口。该层可以由软件api 实现或者使用硬件接口 uart、spi、usb 来控制。

HCI是可选的(具体请参考文章: 三种蓝牙架构实现方案(蓝牙协议栈方 案)),HCI主要用于2颗芯片实现BLE协议栈的场合,用来规范两者之间的通信协议和通信命令等。

L2CAP层(Logic link control and adaptation protocol 逻辑链路控制和自适应协议)

L2CAP 为上层提供数据封装服务。层相当于快递,将数据打包,可以让客户点对点的通信(允许点对多点)。

L2CAP对LL进行了一次简单封装,LL只关心传输的数据本身,L2CAP就要区分是加密通道还是普通通道,同时还要对连接间隔进行管理。

L2CAP 是BLE 蓝牙的复用层,其支持数据的分割和重组,使得较大的报文可以在底层无线电中进行传输。L2CAP 决定了MTU size(Maximum Transmission Unit:最大传输单元),目前芯片支持的MTU_SIZE 为23~247 Bytes。

SMP层(Secure manager protocol 安全管理协议)

SM 层安全服务层,提供配对和密钥的分发,实现安全连接和数据交换。

SMP用来管理BLE连接的加密和安全的,如何保证连接的安全性,同时不影响用户的体验,这些都是SMP要考虑的工作。

GAP层(Generic access profile 通用访问配置文件) ———— 用于连接

BLE协议栈GAP层实现了蓝牙连接功能,其定义了设备的访问模式与流程,包括:设备发现,建立连接,断开连接,初始化安全特性,设备配置等。

GAP 状态(待机、广播、扫描、连接、主从)

GAP 层的蓝牙状态切换图如图5.3所示,每个状态描述如下:

  • 1)待机状态(Standby)
    设备没有传输和发送数据,并且没有连接到任何设备
  • 2)广播状态(Advertiser)
    周期性广播状态
  • 3)扫描状态(Scanner)
    主动地寻找正在广播的设备
  • 4)发起连接状态(Initiator)
    主动向某个设备发起连接
  • 5)已连接,主机状态(Master)
  • 6)已连接,从机状态(Slave)

在这里插入图片描述

BLE 连接请求参数(连接间隔、广播间隔、从机潜伏、监督超时)

BLE 连接参数包含如下:

发送包频率不能高于连接间隔,之前工作中使用的某款蓝牙模组,mcu侧串口发包间隔要有50ms以上,否则就丢包。

在这里插入图片描述

  • 1.Connection Interval缩短,Master和Slave通信更加频繁,提高了数据吞吐速度,缩短了数据发送时间,但也提高了功耗。
  • 2.Connection Interval加长,通信频率降低,数据吞吐速度降低,数据发送等待的时间更长,但这种设置降低了功耗。
  • 3.Slave Latency减少或者设置为0,那么每次连接事件中都需要回复Master的包,当然功耗会上升,但数据发送速度也会提高。
  • 4.Slave Latency加长,功耗下降,数据发送速度降低。

在这里插入图片描述

4)BLE 广播间隔

GAP Role Task(参数配置api、广播内容、连接间隔、断开蓝牙、更新参数)

GAP Role 为一个单独的任务,其主要实现GAP 参数的配置,例如广播内容、连接参数更新参数等。

GAP 层的角色包含如下:

  • 1)Broadcaster:广播者,发射不可连接广播信号
  • 2)Observer:观察者,进行广播信号扫描,但不发起连接
  • 3)Peripheral:发射可连接广播信号,并能够被主机连接
  • 4)Central:扫描广播信号并发起连接。

常用的API 函数包含如下:

2)设置参数

在这里插入图片描述

在这里插入图片描述

GAP Bond Manager(GAP Bond Mgr 连接安全初始化api)

视频里讲的GAP security profiles

GAPBondMgr 用于蓝牙连接时安全特性的初始化。蓝牙安全特性定义如表5.5 所示。

类型 描述
Pairing 配对,进行密钥交换的过程
Encryption 加密,配对完成后或重新建立连接后,数据将加密
Authentication 认证,在配对过程中采用了MITM 保护(如Passcode、NFC 等)
Bonding 绑定,存储加密密钥至flash 存储器以便下次连接使用
Authorization 授权,除了认证外的一种应用层密钥交换方式
OOB 一种MITM 认证方式,密钥交换不通过空中传输,如通过NFC、串口等传输
MITM Man in the Middle Protection. 在配对过程中,通过该方式实现了认证过程,防止通信被监听
Just Works 在配对过程中,不需要MITM,实现了密钥传输

在通常的带有安全特性的连接中,首次连接步骤如下:

  • 1)Pairing:配对,采用Just Works 或者MITM(如passcode)交换秘钥
  • 2)Encryption:使用步骤1)的秘钥加密链路
  • 3)Bonding:保存加密秘钥至Flash

当需要重新建立连接时,可使用首次连接过程中Bonding 中的加密秘钥,对连接链路进行加密。如果取消Bonding 步骤,那么每次连接均需要进行重新配对。

配对绑定配置例程如程序清单5.5 所示。

uint32 passkey = DEFAULT_PASSCODE; uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; uint8 mitm = TRUE; //开启MITM 认证加密 uint8 ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT; uint8 bonding = TRUE; //开启bonding GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); 

在这里插入图片描述

ATT(Attribute protocol 属性协议层)

简单来说,ATT层用来定义用户命令及命令操作的数据,比如读取某个数据或者写某个数据。BLE协议栈中,开发者接触最多的就是ATT

ATT 层 ATT 环境中,允许设备向另外一个设备展示一块特定的数据,称之为“属性” ,展示“属性”的设备称为服务器,与之配对的设备称为客户端

链路层LL状态(主机和从机)与设备的 ATT 角色(服务器和客户端)是相互独立的,链路层的主机设备可以是 ATT 服务器,也可以是 ATT客户端,从机也一样。

BLE引入了attribute概念,用来描述一条一条的数据。Attribute除了定义数据,同时定义该数据可以使用的ATT命令,因此这一层被称为ATT层。

GATT(Service/Characteristic的UUID主从机通信) ———— 用于通信

GATT用来规范attribute中的数据内容,并运用group(分组)的概念对attribute进行分类管理。没有GATT,BLE协议栈也能跑,但互联互通就会出问题,也正是因为有了GATT和各种各样的应用profile,BLE摆脱了ZigBee等无线协议的兼容性困境,成了出货量最大的2.4G无线通信产品。

BLE 协议栈GATT 层用于实现两个设备间的应用层数据通信。GATT 层采用Client/Server 架构,客户端(Client)通过访问服务器端(Server)的服务(Service)与特征(Characteristic),实现数据交互。
GATT 层架构如图5.7 所示。

在这里插入图片描述

在这里插入图片描述

关于服务与特征的描述如下:

  • 用户的应用由一个或多个服务(Service)组成的
  • 每个服务Service 包含一个或多个特征(Characteristic)
  • 每个特征(Characteristic)包含一个或多个属性(Attribute)。属性分别如下(属性是设备之间传输的信息的基本单元,GATT将这些基本单元组织成一块一块的数据,称为Characteristic):
    • a. Characteristic Value:特征值
    • b. Characteristic Declaration:特征申明,描述特征的权限、类型等
    • c. Client Characteristic Configuration:允许GATT 服务器发送notification 或indication 数据。
    • d. Characteristic User Description:描述特征的ASCII 字符串

  • Characteristic Value:特征值的数据,层层解包之后最终想要的值。
  • Characteristic Declaration:特征值数据值的属性,位置和类型。
  • Client Characteristic Configuration:配置GATT服务器主动发送出去的属性(notified),并且期望一个回应(indicated)。
  • Characteristic User Description:描述特征值的ASCII字符串。
  • Handle:属性表中的索引,每个属性有一个唯一的handle。
  • Type:指示属性数据表示的什么样的内容,被称为UUID。有一些UUID被SIG定义,有一些自定义。
  • Permission:限制GATT客户端对属性值的访问权限,注意区分和特征值数据的访问权限。

在这里插入图片描述
GATT里定了发现、读取、写入整个属性过程,特征值、内容配置文件都存在属性表中,下图是GATT某个服务的属性表(TI为例):
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述 上表中,每一行就是一个属性
第1行表示一个服务(比如温湿度服务)的开始
第2, 3,4行是该服务的第一个Characteristic,包含了UUID、Declaration、Char Value、Description。
第5, 6,7行是该服务的第二个Characteristic。。。
特别的是第13行,作用是配置客户端特征值,用于server主动发送数据给client。
蓝牙的应用开发入门就是设定特征值的属性表,然后调用API去接收发送属性。




顶层profile配置文件

由两个部分组成,处于协议栈的最顶层,将协议栈和应用层紧密的连接到一起,开发者对协议栈本身底层原理不用深入理解,就可以进行使用开发。


下面这两个是芯海蓝牙模块开发指南的说明

Lib 库文件

Lib 为蓝牙库文件,大部分蓝牙协议栈在MASK ROM 代码中实现,少部分蓝牙协议栈代码在Lib 库文件中。

外设驱动

为了实现更好的移植性,协议栈将硬件层抽象出了一个HAL 硬件抽象层,当新的硬件平台做好后,只需修改HAL,而不需修改HAL 之上的协议栈的其他组件和应用程序。

蓝牙主机和从机之间传输数据实现

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

一款强大的芯片nRF52840及利用蓝牙5.0实现数据远程采集

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

蓝牙4.0BLE协议栈

BLE开发环境搭建

教程使用IAR,添加BLE蓝牙协议栈文件,类似操作系统的OSAL

OSAL工作原理

在这里插入图片描述

OSAL 为Operating System Abstraction Layer,即操作系统抽象层,支持多任务运行,其中BLE 协议栈、配置文件以及所有的应用程序(app)都在其上运行。它并不是一个传统意义上的操作系统,而是一个允许软件建立和执行事件的循环。OSAL 基于消息驱动,是一个简易的任务轮询系统。

OSAL层一个时间内只有一个任务在运行,CPU可以使用任务调度机制策略,每个任务分配一个特定的时间片,就有点像操作系统,时间片用完了就进行任务切换,由于每个任务执行的时间很短(OSAL每个任务可能就15ms),任务切换的很频繁,就看到一个假象,OSAL同时多个任务在运行。

OSAL 与RTOS 相比,缺少了任务堆栈,系统延时,中断管理,进程间通信,保存上下文的任务调度。

软件功能是由任务事件来实现的,创建一个任务事件需要以下工作:

  • 1)创建任务ID(task identifier);
  • 2)编写任务初始化(task initialization routine)进程,并需要添加到OSAL 初始化进程中,这就是说系统启动后不能动态添加任务;
  • 3)编写任务处理程序;
  • 4)如有需要提供消息服务。

BLE 协议栈的各层都是以OSAL 任务方式实现,由于LL 控制任务的时间要求最为迫切,所以其任务优先级最高。为了实现任务管理,OSAL 通过消息处理(message process),存储管理,计时器定时等附加服务实现。

OSAL 任务事件处理回调函数数组示例如程序清单5.1所示。任务事件处理函数xx_ProcessEvent 顺序需与后续的osalInitTasks 函数内的Task 初始化顺序一致。

先建立一个事件表,保存各任务对应的事件
再建立一个事件处理函数表,保存各任务对应的事件处理函数
将两个表对应起来在这里插入图片描述
在这里插入图片描述


事件处理函数表:
里面保存的都是函数指针

///< The order in this table must be identical to the task initialization calls below in osalInitTask. const pTaskEventHandlerFn tasksArr[] //都是函数指针,指向了事件处理函数 { 
      LL_ProcessEvent, // task 0  HCI_ProcessEvent, // task 1 #if defined ( OSAL_CBTIMER_NUM_TASKS ) OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), // task 2 #endif L2CAP_ProcessEvent, // task 3 SM_ProcessEvent, // task 4 GAP_ProcessEvent, // task 5 GATT_ProcessEvent, // task 6 GAPRole_ProcessEvent, // task 7 #if (DEFAULT_GAPBOND_MGR_ENABLE==1) GAPBondMgr_ProcessEvent, // task 8 #endif GATTServApp_ProcessEvent, // task 9 SimpleBLEPeripheral_ProcessEvent, // task 10 }; 

TASK初始化(osal_start_system调用初始化函数osalInitTasks)

为了使用OSAL,在main 函数的最后要启动一个名叫osal_start_system 的进程,该进程会调用由特定应用决定的初始化函数osalInitTasks。osalInitTasks 函数示例如程序清单5.2所示。

事件表:

接上文程序 const uint8 tasksCnt = sizeof(tasksArr)/sizeof(tasksArr[0]); uint16 *tasksEvents; / * @fn void osalInitTasks(void) * @brief This function invokes the initialization function for each task. * @param none * @return none */ void osalInitTasks( void ) { 
      uint8 taskID = 0; tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); //tasksEvents事件表首地址 通过这个指针可以访问到事件表的每一项  //如果有事件发生,就查找函数表,找到对应事件的处理函数进行处理 //处理完成继续访问事件表,看是否还有其他事件要发生 基于事件驱动的轮询操作系统 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); /* LL Task */ LL_Init( taskID++ );//ID越小,优先级越高 LL控制任务的时间要求最为迫切,任务优先级最高 /* HCI Task */ HCI_Init( taskID++ ); #if defined ( OSAL_CBTIMER_NUM_TASKS ) /* Callback Timer Tasks */ osal_CbTimerInit( taskID ); taskID += OSAL_CBTIMER_NUM_TASKS; #endif /* L2CAP Task */ L2CAP_Init( taskID++ ); /* SM Task */ SM_Init( taskID++ ); /* GAP Task */ GAP_Init( taskID++ ); /* GATT Task */ GATT_Init( taskID++ ); /* Profiles */ GAPRole_Init( taskID++ ); #if(DEFAULT_GAPBOND_MGR_ENABLE==1) GAPBondMgr_Init( taskID++ ); #endif GATTServApp_Init( taskID++ ); /* Application */ SimpleBLEPeripheral_Init( taskID );//GAP GATT的配置 视频中串口、LED、ADC实验也在此函数内完成 } 

osalInitTasks 函数逐个调用BLE 协议栈各层的启动进程来初始化协议栈,并设置一个任务的8bit 任务ID(task ID)。osalInitTasks 函数执行完成后,将跳入循环等待执行任务,系统启动完成。

使用OSAL 时,注意事项如下:

  • 1)任务优先级决定于任务ID,任务ID 越小,优先级越高
  • 2)BLE 协议栈各层的任务优先级比应用程序的高。

TASK与event 处理原理:位运算,events占2个字节最多定义16个事件(osal_start_system调用运行函数osal_run_system)

OSAL 完成TASK 初始化后,将调用osal_start_system 函数开始运行OSAL系统。系统是以一个死循环的形式工作的,其函数实现如程序清单5.3 所示,该代码在MaskROM 中运行。

void osal_start_system( void ) { 
      for(;;) // Forever Loop { 
      osal_run_system(); } } 

在这里插入图片描述
在这里插入图片描述

OSAL 任务事件采用16 位变量定义,每1 位表示1 个唯一的事件标识,因此每个任务最多可定义16个不同类型事件。OSAL 事件处理流程图如图5.1所示。

osal_run_system 函数(在osal_start_system 函数的死循环内调用)流程如下:

  • 1)更新OSAL Timer,以便设置timeout 事件,同时将事件查询task id 设置为0
  • 视频中此处Hal_ProcessPoll(),HAL层信息处理
  • 2)判断当前task id 的任务是否有事件发生,如有跳转至步骤3),如无则进行task id 自增,并继续执行步骤2)的判断流程。当task id 超出任务数量时,跳转至步骤4)
  • 3)执行tasksArr 回调函数数组内的对应xx_ProcessEvent 函数,执行完成后,退出osal_run_system 函数,并在下次循环里继续开始整个流程。
  • 4)执行Sleep 调度,当唤醒后,继续开始整个流程。
    在这里插入图片描述

当事件处理程序处理完相应事件后,需要清除相应标识。如未清除相应标识,OSAL 会认为事件还没有处理完成,后续会继续调用相应处理函数进行处理。

如在simpleBLEPeripheral(从机) 例程中,当事件START_DEVICE_EVT 发生,其处理函数SimpleBLEPeripheral_ProcessEvent 就运行,结束后返回16bit 事件变量,并清除事件标识SBP_START_DEVICE_EVT。程序代码如程序清单5.4 所示。

if ( events & SBP_START_DEVICE_EVT ) { 
      …… return ( events ^ SBP_START_DEVICE_EVT ); } 

原理分析:events占2个字节16位,即最多定义16个事件,通过位运算中的按位与运算,全部为1则为1,进入该事件处理函数,处理完执行按位异或运算,相同为0,清除该事件标志位。

OSAL函数api介绍

OSAL 添加事件函数

视频课程里介绍的这些api在OSAL.c文件里面

  • 1)立即事件
uint8 osal_set_event( uint8 task_id, uint16 event_flag ) 调用该函数后将产生立即事件。 
  • 2)定时器事件
uint8 osal_start_timerEx( uint8 task_id, uint16 event_id, uint32 timeout_value ) 调用该函数将设置一个软件定时器,超时后将产生对应事件。超时时间timeout_value 单位为ms。 
  • 3)自动加载定时器事件
uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint32 timeout_value ); 调用该函数将设置一个自动加载的软件定时器,超时后将产生对应事件,并自动重新加载定时器。 超时时间timeout_value 单位为ms。 

OSAL内存管理函数

视频课程里介绍的这些api在OSAL.c文件里面

OSAL 提供了基本的内存管理函数。内存管理函数定义如下:

1)内存分配

void *osal_mem_alloc( uint16 size ) 调用该函数将分配指定size 的内存空间,并返回内存首地址。当分配失败时,将返回NULL

2)内存释放

void osal_mem_free( void *ptr ) 调用该函数将释放之前分配的内存空间。 

OSAL消息通信函数

OSAL 消息机制实现了不同子系统之间的通信。消息即为数据,数据种类和长度都不限定。消息管理函数定义如下:

  • 1)OSAL 消息创建
uint8 * osal_msg_allocate(uint16 len ); 发送消息前,需要调用该函数创建消息占用的内存空间(内部已经包含了osal_mem_alloc 函数功 能)。需要为该函数指定空间大小,该函数返回内存空间地址指针。 
  • 2)OSAL 消息发送
uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ) 将待发送的消息内容拷贝至msg_ptr 内存空间后,调用该函数向指定任务发送消息。调用该函数将产 生SYS_EVENT_MSG 事件并告知对应Task。 
  • 3)OSAL 消息接收
uint8 *osal_msg_receive( uint8 task_id ) 目标Task 判断有SYS_EVENT_MSG 事件后,将调用该函数从指定任务接收消息数据。 
  • 4)OSAL 消息释放
uint8 osal_msg_deallocate( uint8 *msg_ptr ); 消息处理完成后,需要调用该函数来释放内存空间(内部已经包含了osal_mem_free 函数功能)。 

SYS_EVENT_MSG(0x8000)是OSAL 保留的消息处理事件,所有任务均包含该事件。该事件用于消息的传递,即将参数从一个任务传递给另一个任务,详情请参考“OSAL 消息”章节。

其他的OSAL层API函数接口

OSAL UART实验

在这里插入图片描述

OSAL 主从机通信实验(添加特征值)

主从机通信通过特征值实现的,类似标签,有四个属性:长度、读写、UUID、功能。

本实验实现了R6的功能。

在这里插入图片描述
UUID
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

set函数添加char6

在这里插入图片描述

在这里插入图片描述
get函数添加char6

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

change回调函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

实验现象

从机上电开始广播,主机(比如手机蓝牙助手)进行通信。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

从机上电如何实现广播

在SimpleBLEPeripheral_Init函数里面,将从机广播功能设置为TRUE

在这里插入图片描述

主机自动扫描

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主机连接设备

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从机串口的数据处理

在这里插入图片描述

在这里插入图片描述

从机蓝牙读属性的数据处理

在这里插入图片描述

主机串口数据处理

在这里插入图片描述

在这里插入图片描述

OSAL BLE获得多个特征值句柄实验

主机当客户端代码分析

在这里插入图片描述
修改事件函数simpleBLEGATTDiscoveryEvent

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

OSAL BLE自动重连设备实验

默认断开设备主机是不能重新连接的,

在这里插入图片描述

OSAL BLE的绑定和配对实验

一般要输入密码,安全,限制非法连接

在这里插入图片描述
在这里插入图片描述
不要每次都输入密码绑定

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

OSAL操作系统分析

OSAL操作系统分析

蓝牙协议栈遇到的问题总结(主从模式、MAC地址、RSSI)

在学习开发蓝牙协议栈遇到的问题总结:

1.蓝牙设备号BD_ADDR就是MAC地址,不同于uuid,uuid是服务号,作为唯一标识符。

2.scanRspData数组是扫描回应数据数组,用户可以自定义设备名。advertData数组是广播数据数组,主要是包含在广播里的数据信息。

协议栈中的SimpleBLEPeripheral是从机模式,主要是广播信息,让其他设备知道。
SimpleBLECentral是主机模式,主要是与从机建立连接。
读写characteristic可以理解为GATT层的client向service发送数据,或者是service向client端发送数据。

主机设备可以是client(客户端),也可以是service(服务器),即主机向从机发送数据,从机主动向主机发送数据。

主机向从机读写数据调用GATT_WriteCharValue函数和ATT_ReadCharValue函数。如下:

if ( simpleBLEDoWrite ) { 
      // Do a write attWriteReq_t req; req.handle = simpleBLECharHdl+2; req.len = 2; req.value[0] = simpleBLECharVal; req.sig = 0; req.cmd = 0; status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId ); if ( status == SUCCESS ) { 
      NPI_WriteTransport(“write ok\r\n”, 10); simpleBLEProcedureInProgress = TRUE; simpleBLEDoWrite = !simpleBLEDoWrite; } else { 
      // Do a read attReadReq_t req; req.handle = simpleBLECharHdl+2; status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId ); } 

从机和主机发送数据机制不一样。主机用write命令,从机用Notification通知命令。从机向主机发送数据调用GATT_Notification函数,如:

static attHandleValueNoti_t Report ; uint16 GetHandle; noti.len = 1; noti.value[0] = GetLen; GATT_Notification(GetHandle, &Report, FALSE ); 
if ( events &SBP_ADV_RGB_EVT ) { 
      //P0_3=~P0_3; advertData[6]= battMeasure();//获取电池电量 GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); osal_start_timerEx(simpleBLEBroadcaster_TaskID,SBP_ADV_RGB_EVT,1000); return ( events ^ SBP_ADV_RGB_EVT ); } 
case GAP_DEVICE_INFO_EVENT: { 
      if( (pEvent->deviceInfo.pEvtData+7)==0xA7) simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType, pEvent->deviceInfo.rssi ,(pEvent->deviceInfo.pEvtData+6)); } break; 

IOS蓝牙iBeacon协议(UUID、Major、Minor、RSSI)

芯海蓝牙第一个例程里用到

ibeacon和蓝牙有什么区别_它们的区别在哪里

7-iBeacon参数

蓝牙IBEACON协议案例详细解析

手机蓝牙APP工具的使用(nrf Connect)

摘自:nrf Connect低功耗蓝牙APP工具的使用

在这里插入图片描述

扫描者

点击SCAN或者下拉界面,可以刷新设备列表,右滑界面可以看到每个设备的信号强度的变化曲线图,不同颜色代表不同的设备。

在这里插入图片描述

连接设备

可写与可监听

在这里插入图片描述

写操作(APP到从设备)

写操作,数据从APP端发送到从设备端

监听操作(从设备到APP0)

数据从从设备端发送到APP端

JDY-10M蓝牙模块使用教程(AT指令)

蓝牙开发介绍
在这里插入图片描述
在这里插入图片描述
JDY-10M模块介绍
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述






在这里插入图片描述
JDY-10M引脚说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

普通数据收发AT指令
使用AT指令,隐藏了底层的蓝牙通信协议栈

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

控制功能数据AT指令

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

手机APP通信
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

蓝牙广播数据格式和简单易懂的蓝牙视频教程

博文及对应的B站视频。

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

蓝牙连接过程及对应的断连原因

我们知道BLE通信过程是建立在连接基础之上的,按角色不同可以分为蓝牙主设备、蓝牙从设备,也叫中央设备和外围设备。以下简称为主机和从机。一次蓝牙通信,通常由主机发起,从机响应。我在调试蓝牙主机程序的过程中,发现经常会出现“秒断”的现象,即主机连接上从机,然后立马又断开了,断开原因是0x3e。经过查找资料和抓包分析,终于搞清楚了发生这个现象的原因。

先看下BLE核心规范《 Core_v4.2》中对0x3e的断开原因是怎么说明的,在文档的385页可以找到相关描述:

在这里插入图片描述

从字面意思看,是非常笼统的,意思发起了一个连接,但这个连接建立失败了。要想弄清楚这个问题的原因,必须要对蓝牙的连接过程有所了解。下面就结合BLE核心规范《 Core_v4.2》来看一下蓝牙的连接过程。在这个文档的第144页,可以找到和连接过程相关的描述:

在这里插入图片描述

上图中,设备A是蓝牙主机,B是蓝牙从机。BLE的连接过程,大致分为6个步骤:

1)主机进入连接态,侦听待连接设备的广播包。如果在指定时间内没侦听到,会导致连接超时,这个时间由开发者指定。

2)主机成功接收到从机的广播包。

3)主机发送一个连接请求包。

4)主机发出连接请求包后,不管从机有没有收到,都会立即转入连接状态,同时报给用户层一个“已连接上”的消息,也就是图中的4A。如果从机能收到这个连接请求包,则从机也立即转入连接状态,并报给用户层一个“已连接上”的消息。如果从机未能收到连接请求包,则不会发4B的消息。

5)主机随即发送一个同步包。

6)从机收到同步包后,回给主机一个同步包,然后不停循环5和6两个步骤,连接才是真正建立了。如果5和6任何一个包丢失,都会导致连接建立失败,报0x3e的断开原因。

知道了BLE连接的详细过程,再结合抓包工具抓取连接过程的数据包分析,可以很容易发现,通常是丢失第5步或者第6步的数据包,导致连接建立失败。而这两个包丢失,通常发生在周围存在很多蓝牙设备,导致信道十分拥挤的情况下。通过在空旷无多余蓝牙设备的地方实验发现,出现这个现象的概率大大降低,由此验证了这个推论。当周围蓝牙设备不可避免地过多时,应用层可以通过多次重连来规避这个问题。

  • 如果第2步的广播包收不到,报错0x08;
  • 连接过程如果能走到第4步,但缺失第5步,会先连接上,但立马断开,断开原因报0x3E;
  • 如果能走到第6步之后, 但是中途PDU没了,例如某一方断电,也会报0x08

蓝牙官方资料下载地址(官方)

蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119048.html

(0)
上一篇 2025-11-08 13:10
下一篇 2025-11-08 13:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信