大家好,欢迎来到IT知识分享网。
目录
- 蓝牙配对和绑定
- 蓝牙4.0 BLE
- 信道(RF Channel)
- BLE协议栈分层
-
- PHY层(Physical layer 物理层)
- LL层(Link Layer 链路层)
- HCI层(Host controller interface 主机控制接口层)
- L2CAP层(Logic link control and adaptation protocol 逻辑链路控制和自适应协议)
- SMP层(Secure manager protocol 安全管理协议)
- GAP层(Generic access profile 通用访问配置文件) ———— 用于连接
- ATT(Attribute protocol 属性协议层)
- GATT(Service/Characteristic的UUID主从机通信) ———— 用于通信
- 顶层profile配置文件
- Lib 库文件
- 外设驱动
- 蓝牙主机和从机之间传输数据实现
- 一款强大的芯片nRF52840及利用蓝牙5.0实现数据远程采集
- BLE开发环境搭建
- OSAL工作原理
- OSAL函数api介绍
- OSAL UART实验
- OSAL 主从机通信实验(添加特征值)
- OSAL BLE获得多个特征值句柄实验
- OSAL BLE自动重连设备实验
- OSAL BLE的绑定和配对实验
- OSAL操作系统分析
- 蓝牙协议栈遇到的问题总结(主从模式、MAC地址、RSSI)
- IOS蓝牙iBeacon协议(UUID、Major、Minor、RSSI)
- 手机蓝牙APP工具的使用(nrf Connect)
- JDY-10M蓝牙模块使用教程(AT指令)
- 蓝牙广播数据格式和简单易懂的蓝牙视频教程
- 蓝牙连接过程及对应的断连原因
- 蓝牙官方资料下载地址(官方)
蓝牙配对和绑定
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



















上表中,每一行就是一个属性

















































































