这里写目录标题
- 0. 蓝牙概述
- 蓝牙技术的特点
- 1. 常见的蓝牙模块
- 2. HC-05/HC-06
- 2.1 概念
- 2.2 区别
- 3. STM32使用HC-05通信
- 3.1 方法
- 3.2 示例代码
0. 蓝牙概述
蓝牙(Bluetooth)是一种用于无线通信的技术标准,允许设备在短距离内进行数据交换和通信。它是由爱立信(Ericsson)公司在1994年推出的,以取代传统的有线连接方式,使设备之间能够实现低功耗、低成本的数据传输和通信。
蓝牙技术的特点
-
无线通信:蓝牙允许设备在近距离内(通常是10米左右,具体取决于设备版本)进行通信,无需使用电缆或其他物理连接。
-
低功耗:蓝牙技术被设计为低功耗的通信方式,这使得它在移动设备上广泛使用,如智能手机、平板电脑、蓝牙耳机等。
-
多设备连接:蓝牙允许一个主设备(如手机)同时连接多个从设备(如蓝牙耳机、蓝牙音箱等),实现更灵活的数据传输和通信。
-
通用性:蓝牙技术在许多设备和应用中得到广泛应用,例如无线耳机、键盘、鼠标、汽车蓝牙连接、智能家居设备等。
-
安全性:蓝牙技术在不断发展和改进中,以提高其安全性,以防止未经授权的访问和数据泄露。
蓝牙技术在不同的版本中有不同的特性和功能,从经典蓝牙(Bluetooth Classic)到低功耗蓝牙(Bluetooth Low Energy,简称BLE),每个版本都针对不同的应用场景和需求。
1. 常见的蓝牙模块
-
HC-05/HC-06:
- HC-05和HC-06是广泛使用的经典蓝牙模块,常用于与单片机(如Arduino)进行无线通信。
- 它们基于蓝牙2.0标准,支持串口通信(UART)协议,使得与单片机的连接和数据交换相对简单。
- HC-05可作为主设备或从设备,支持蓝牙SPP(串口通信)和AT命令模式。
- HC-06通常作为从设备,仅支持蓝牙SPP模式。
- 它们具有基本的通信范围,通常在10米左右。
-
HM-10/CC2541:
- HM-10和CC2541是低功耗蓝牙(BLE)模块,适用于物联网(IoT)设备和传感器网络。
- 它们基于蓝牙4.0标准,具有低功耗和短距离通信的特点。
- 它们支持BLE通信协议,如GATT(通用属性配置文件)和ATT(属性协议),用于数据传输和连接管理。
- HM-10具有较大的功能集,包括主设备和从设备模式,而CC2541主要作为从设备。
- 它们通常用于连接和控制传感器、智能家居设备等。
-
RN42/RN52:
- RN42和RN52是经典蓝牙模块,由Microchip(以前是Roving Networks)生产。
- 它们基于蓝牙2.1+EDR标准,提供了丰富的功能和易于使用的接口。
- 这些模块支持串口通信(UART)协议,具有较大的通信范围(通常在30米以上)。
- 它们适用于各种应用,如音频传输、数据通信和蓝牙配对。
- RN52还提供了额外的音频功能,如立体声音频传输和音频配置选项。
-
ESP32:
- ESP32是一款强大的Wi-Fi和蓝牙组合模块,由Espressif Systems开发。
- 它集成了双核处理器、Wi-Fi、蓝牙、低功耗技术和丰富的外设接口。
- ESP32支持蓝牙经典和低功耗蓝牙(BLE),具有较大的灵活性和功能性。
- 它广泛应用于物联网(IoT)应用、嵌入式系统和智能设备开发。
2. HC-05/HC-06
2.1 概念
HC-05和HC-06是两种常见的经典蓝牙模块,它们在设计和功能上有一些区别。以下是对它们进行详细讲解:
-
HC-05:
- HC-05是一款功能强大的经典蓝牙模块,由爱信电子(EGBT)生产。
- 它基于蓝牙2.0标准,支持多种传输协议,包括串口通信(UART)和蓝牙SPP(串口通信)。
- HC-05可以在主设备模式(Master)或从设备模式(Slave)之间切换,具有较高的灵活性。
- 它支持蓝牙连接密码的设置,以提高安全性。
- HC-05具有6个引脚,包括VCC(供电)、GND(接地)、TXD(发送数据)、RXD(接收数据)、STATE(状态)和EN(使能)。
- STATE引脚可用于检测连接状态和模块工作模式。
- HC-05可以通过AT指令进行配置和控制,例如更改蓝牙名称、波特率、配对密码等。
-
HC-06:
- HC-06是另一款常见的经典蓝牙模块,也由爱信电子(EGBT)生产。
- 与HC-05相比,HC-06相对简化,主要用于从设备模式(Slave)。
- 它仅支持蓝牙SPP(串口通信)协议,无法切换到主设备模式。
- HC-06具有4个引脚,包括VCC(供电)、GND(接地)、TXD(发送数据)和RXD(接收数据)。
- 它没有STATE和EN引脚,因此无法提供与连接状态和工作模式相关的信息。
- HC-06可以直接与其他主设备(如智能手机或电脑)进行配对和通信。
- 类似于HC-05,HC-06也可以通过AT指令进行配置,例如更改蓝牙名称和配对密码。
2.2 区别
-
工作模式:
- HC-05:HC-05模块可以在主设备模式(Master)或从设备模式(Slave)之间切换。这意味着它可以充当蓝牙主设备与其他从设备建立连接,也可以作为从设备接受来自主设备的连接请求。
- HC-06:HC-06模块主要用作从设备模式(Slave)。它无法切换为主设备模式,只能接受来自主设备的连接请求。
-
支持的协议:
- HC-05:HC-05模块支持多种传输协议,包括串口通信(UART)和蓝牙SPP(串口通信)协议。它可以通过这些协议与其他设备进行数据传输和通信。
- HC-06:HC-06模块仅支持蓝牙SPP(串口通信)协议。它没有UART传输协议的支持,因此在使用HC-06与其他设备通信时,需要通过串口进行数据传输。
-
引脚和功能:
- HC-05:HC-05模块具有6个引脚,包括VCC(供电)、GND(接地)、TXD(发送数据)、RXD(接收数据)、STATE(状态)和EN(使能)。STATE引脚可以用于检测连接状态和模块工作模式。
- HC-06:HC-06模块相对简化,只有4个引脚,包括VCC(供电)、GND(接地)、TXD(发送数据)和RXD(接收数据)。它没有STATE和EN引脚,因此无法提供与连接状态和工作模式相关的信息。
-
应用场景:
- HC-05:由于HC-05支持主设备模式和多种传输协议,它在需要作为主设备连接其他从设备的应用中较为常见。它适用于需要灵活控制连接的项目。
- HC-06:HC-06主要用作从设备,适用于需要接受来自主设备连接的应用。它适合简单的蓝牙串口通信场景。
根据具体的应用需求来选择使用HC-05还是HC-06。如果需要主设备模式、多种传输协议的支持以及与其他设备的灵活连接,HC-05可能是更好的选择。如果只需要简单的从设备模式和蓝牙串口通信功能,HC-06可以满足需求。
3. STM32使用HC-05通信
3.1 方法
-
连接硬件:
- 将HC-05模块的VCC引脚连接到STM32的3.3V电源引脚,GND引脚连接到STM32的地引脚。
- 将HC-05模块的TXD引脚连接到STM32的一个UART接收引脚(例如USART1_RX),RXD引脚连接到STM32的一个UART发送引脚(例如USART1_TX)。
- 如果需要进行模块的配置或进入AT命令模式,可以将HC-05模块的EN引脚连接到STM32的一个GPIO引脚,并在代码中控制该引脚的状态。
-
配置串口:
- 在STM32的代码中,需要配置相应的UART串口进行与HC-05模块的通信。您可以使用STM32的HAL库或直接使用寄存器级编程进行配置。
- 设置串口的波特率、数据位、停止位和校验位,以与HC-05模块的通信参数相匹配。
- 启用串口的接收和发送中断,以便进行数据的收发。
-
与HC-05通信:
- 使用UART发送函数将数据发送给HC-05模块。例如,使用HAL库时,可以使用
HAL_UART_Transmit()
函数。 - 使用UART接收函数接收来自HC-05模块的数据。例如,使用HAL库时,可以使用
HAL_UART_Receive()
函数。 - 根据HC-05模块的通信协议和AT指令集,编写相应的代码来控制HC-05模块的行为,例如配置模块参数、建立蓝牙连接等。
- 使用UART发送函数将数据发送给HC-05模块。例如,使用HAL库时,可以使用
-
处理数据:
- 在STM32的代码中,根据您的应用需求,对从HC-05模块接收到的数据进行处理。您可以将数据发送到其他设备,进行相应的处理或响应等。
3.2 示例代码
#include "stm32f4xx.h"
#include "stm32f4xx_hal.h"
// 定义串口句柄和接收缓冲区
UART_HandleTypeDef huart1;
char rxBuffer[50];
int rxIndex = 0;
// 函数原型
void SystemClock_Config(void);
void GPIO_Init(void);
void UART_Init(void);
void UART_Transmit(char *data);
void UART_Receive(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
GPIO_Init();
UART_Init();
while (1)
{
// 接收数据
UART_Receive();
// 如果收到换行符'\n',表示接收到完整的一行数据
if (rxBuffer[rxIndex - 1] == '\n')
{
// 处理接收到的数据
// 在这里可以添加您的处理代码,例如解析数据、响应等
// 发送数据回复
UART_Transmit("Received: ");
UART_Transmit(rxBuffer);
// 清空接收缓冲区和索引
memset(rxBuffer, 0, sizeof(rxBuffer));
rxIndex = 0;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
void GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void UART_Init(void)
{
__HAL_RCC_USART1_CLK_ENABLE();
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
}
void UART_Transmit(char *data)
{
HAL_UART_Transmit(&huart1, (uint8_t *)data, strlen(data), HAL_MAX_DELAY);
}
void UART_Receive(void)
{
HAL_UART_Receive_IT(&huart1, (uint8_t *)&rxBuffer[rxIndex], 1);
rxIndex++;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1, (uint8_t *)&rxBuffer[rxIndex], 1);
rxIndex++;
}
}
将HC-05模块连接到STM32的USART1串口(PA9为USART1_TX,PA10为USART1_RX)。它使用了HAL库进行串口的初始化、数据发送和接收。
在main()
函数中,它通过轮询的方式接收来自HC-05模块的数据,并在接收到换行符’\n’后对数据进行处理和回复。您可以根据需要修改处理和回复的代码。
UART_Init()
函数用于配置USART1串口的参数,包括波特率、数据位、停止位、校验位等。
UART_Transmit()
函数用于发送数据到HC-05模块。
UART_Receive()
函数使用中断方式接收来自HC-05模块的数据,并将接收到的数据存储在rxBuffer
中。
HAL_UART_RxCpltCallback()
函数是UART接收完成中断的回调函数,当每次接收到一个字节的数据时,它会触发下一次接收。