学习目标
- 理解原理图
- 理解蓝牙调试的流程
-
学习内容
蓝牙协议
蓝牙协议是一个很丰富的协议,总体可以分为:
基础协议(Basic Rate/Enhanced Data Rate,BR/EDR):也称为蓝牙经典蓝牙协议,使用2.4GHz频段进行通信,支持点对点、广播和组播通信等。
- 高速协议(Bluetooth High Speed,HS):支持3种速率,分别为1Mbps、2Mbps和3Mbps,主要用于数据传输。
- 低功耗蓝牙协议(Bluetooth Low Energy,BLE):也称为蓝牙智能协议,主要用于低功耗应用场景,例如传感器、健康监测设备、智能家居等。
- 蓝牙Mesh协议:一种基于蓝牙技术的无线Mesh网络协议,适用于物联网设备间的通信。
对于基础协议(Basic Rate/Enhanced Data Rate,BR/EDR),可以具体分为以下几个协议栈:
- L2CAP(逻辑链路控制和适配协议):提供数据报文的封装和多路复用等功能。
- RFCOMM(无线串行端口协议):提供类似于串口的数据通信服务。
- SDP(服务发现协议):用于设备间的服务发现和信息查询。
- GAP(通用访问协议):提供设备发现、连接和配对等基础功能。
- GATT(通用属性协议):提供设备间的数据交换服务。
我们今天要学习的蓝牙模组的SPP模式,就是这个基础协议中的RFCOMM协议。
SPP (Serial Port Profile):
SPP代表串口配置文件,它是蓝牙技术中的传统蓝牙协议之一。SPP旨在模拟传统的串口通信,使设备能够通过蓝牙建立虚拟的串口连接,并通过该连接进行数据传输。这种协议通常用于传输简单的串行数据,例如从一个设备向另一个设备发送文本、命令或其他基本数据。
BLE (Bluetooth Low Energy):
BLE代表低功耗蓝牙,也被称为蓝牙4.0或蓝牙Smart。它是蓝牙技术的另一种变体,专门设计用于低功耗设备之间的通信。BLE主要用于与物联网(IoT)设备、传感器、健康设备和其他需要低功耗和较短通信距离的设备进行通信。相比传统的蓝牙,BLE在连接过程和数据传输中消耗更少的能量。
对于低功耗蓝牙协议(BLE),它使用的协议栈与经典蓝牙协议(BR/EDR)不同,主要由以下4层协议组成:
- Physical Layer(物理层):处理无线信号的收发和解调等任务。
- Link Layer(链路层):处理广播、扫描、连接和通信等任务。
- Attribute Protocol(属性协议):基于GATT协议实现,用于管理设备之间的数据交换。
- Generic Access Profile(通用访问协议):提供设备发现、连接和配对等基础功能。
BLE是蓝牙4.0提出的低功耗解决方案,今天学习的模组也是支持的,不过需要设备端额外的进行开发。
主从设备
蓝牙设备间进行连接,我们称为配对。配对的双方分主(Master)从(Slave)。
蓝牙连接的设备分为主设备(Master)和从设备(Slave),主设备负责发起连接请求,而从设备则负责响应连接请求。
在蓝牙传输数据的时候,主设备扮演着控制角色,负责传输控制信号和数据,从设备则被动地接受控制信号和数据。主设备可以连接多个从设备,但每个从设备只能连接一个主设备。
在蓝牙连接中,主设备需要具备扫描和连接两个基本功能,扫描功能用于搜索周围的蓝牙设备,连接功能用于和蓝牙设备建立连接并传输数据。从设备则只需要具备连接功能。
在蓝牙4.0之后,新增了低功耗蓝牙(Bluetooth Low Energy, BLE)协议,它也被称为蓝牙Smart。相比于传统的蓝牙,BLE具有低功耗、短距离、低速率等特点,可以用于物联网等需要长时间运行、低功耗的应用场景。在BLE中,主设备和从设备没有严格的区分,设备可以在不同的时间扮演主设备或从设备的角色,称之为主从切换(Master-Slave Switching)。
原理图
蓝牙模组JDY-33
JDY-33 蓝牙基于蓝牙 3.0 SPP+BLE 设计,这样可以支持 Windows、Linux、android、IOS 数据透传,工作频段 2.4GHZ,调制方式 GFSK,最大发射功率 6db,最大发射距离 30 米,支 持用户通过 AT 命令修改设备名、波特率等指令,方便快捷使用灵活.
详情见模组手册:
JDY-33-V2.2蓝牙SPP串口透传模块手册.pdf
JDY-33-V2.2带底板手册.pdf
蓝牙模块调试测路
上图为完整的开发调试过程中,交互的设备关系图。
其中我们的开发板中包括了MCU和蓝牙模组,和蓝牙模组通讯采用的是串口,在当前开发板中采用的是串口2.
我们在开发过程中,如果要对开发板进行打印输出调试,采用的时串口1。
开发板中的蓝牙模组可以和其他蓝牙设备配对,两个设备可以进行相互通讯。
AT指令测试
AT是Attention的缩写,表示指令开始信号。AT指令集常见于通讯设备的内部控制指令。如蓝牙、WIFI模块等等。
当前的蓝牙模块可以通过AT指令来获取或者设置一些信息。我们需要通过发送AT指令的方式来进行操作,因此我们需要一个调试环境,下图中,我们使用PC进行调试:
PC端通过串口1将AT指令发送给我们的MCU,MCU收到指令后,通过串口2转给蓝牙模组,这样就间接的通过PC来调试蓝牙模组了。
通过调试工具进行测试:
注意:AT指令结束需要加上换行符号,否则蓝牙模组不会应答数据。
测试指令
AT
+Ok
查询版本号
AT+VERSION
+VERSION=JDY-33-V2.23,Bluetooth V3.0+BLE
-
查询连接状态
AT+STAT
+STAT=00
00:表示没有连接
- 01:表示BLE连接
-
设置深度睡眠
当没有和其他蓝牙设备连接时,可以设置深度睡眠
AT+SLEEP
+Ok
如果设置了深度睡眠,蓝牙模组就停止工作,其他指令将不再有响应。
如果要重新激活蓝牙模组,需要触发蓝牙的EN引脚为下降沿,这样蓝牙模组又可以工作。波特率查询和设置
当没有和其他蓝牙设备连接时,可以查询波特率
AT+BAUD
+BAUD=4
2:2400
- 3:4800
- 4:9600
- 5:19200
- 6:38400
- 7:57600
- 8:115200
- 9:128000
- A:230400
- B:256000
默认:9600
AT+BAUD4
+OK
- 命令后面的数字参考上面对应的波特率
设置完成后,波特率会固化到模组的存储中,即使断电重启,也不会发生变化。因此要注意波特率配置的值,否则将无法联通成功
SPP广播名称查询和设置
AT+NAME
+NAME=JDY-33-SPP
默认名称为
JDY-33-SPP
AT+NAMEitheima
+OK
name 后面是SPP广播名称
-
SPP蓝牙配对密码查询和设置
AT+PIN
+PIN=1234
查询结果为配对密码
AT+PIN8888
+OK
-
复位
AT+RESET
+OK
断开指令
AT+DISC
+OK
恢复出厂设置
AT+DEFAULT
+Ok
蓝牙设备间通讯
我们的蓝牙模组做为蓝牙设备的一方,需要和其他蓝牙设备进行通讯
其他设备可以是电脑,手机等等,具有蓝牙模块的设备。
为了调试方便,我们使用我们的笔记本电脑进行调试,现在的笔记本电脑都有蓝牙模块。
笔记本蓝牙调试
我们要调试的是开发板端和笔记本蓝牙端的通讯。我们为了方便调试,我们对两端提供一些调试便利。
我们先看开发板端的调试方式:
其实更具体点,应该是通过PC端的串口调试工具进行给蓝牙模组进行调试。
接下来我们看看蓝牙设备端部分,如果要调试设备端的蓝牙通讯,同样需要有工具进行调试。
如果将两者串起来就是一套完整的测试链:
设备端蓝牙转串口配置
- 打开设置中的蓝牙按照下图,将笔记本的蓝牙和开发板的蓝牙进行配对。
PIN值为1234,输入,然后点击连接。
- 配对完成后。我们的开发板和笔记本的蓝牙就联通了,为了调试方便,需要将笔记本的蓝牙转换成串口。
- 通过串口调试笔记本端的蓝牙和开发板的蓝牙
手机蓝牙调试
下载蓝牙调试宝,进行调试
找到JDY-33-SPP
点击连接
输入配对密码1234
通过调试界面进行调试。
蓝牙驱动编写
开发板中,通过串口进行蓝牙数据的读写,因此,只需要做好读写操作即可.
#ifndef __BLUETOOTH_H__
#define __BLUETOOTH_H__
#include "config.h"
#include "UART.h"
#define BT_EN P03
#define BT_RXD P10
#define BT_TXD P11
#define BT_STATE P02
#define BT_PIN_INIT() {P0M0 &= ~0x0c; P0M1 &= ~0x0c; P1M0 &= ~0x03; P1M1 &= ~0x03;}
void BT_init();
void BT_send(u8 dat);
void BT_recv();
extern void BT_on_recv(u8 dat);
#endif
#include "Bluetooth.h"
static void UART_config(void) {
COMx_InitDefine COMx_InitStructure; //结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer2; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
COMx_InitStructure.UART_BaudRate = 9600ul; //波特率, 一般 110 ~ 115200
COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
COMx_InitStructure.UART_Interrupt = ENABLE; //中断允许, ENABLE或DISABLE
COMx_InitStructure.UART_Priority = Priority_0; //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
COMx_InitStructure.UART_P_SW = UART2_SW_P10_P11; //切换端口, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
UART_Configuration(UART2, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
}
void BT_init() {
BT_PIN_INIT();
UART_config();
}
void BT_send(u8 dat) {
}
void BT_recv() {
u8 i;
if(COM2.RX_TimeOut > 0) {
//超时计数
if(--COM2.RX_TimeOut == 0) {
if(COM2.RX_Cnt > 0) {
for(i=0; i<COM2.RX_Cnt; i++) {
// TODO: RX2_Buffer[i]存的是接收的数据
// TODO: 做具体的逻辑
BT_on_recv(RX2_Buffer[i]);
}
}
COM2.RX_Cnt = 0;
}
}
}
练习题
- 通过蓝牙串口发送消息给小车,控制小车运动。