STM32蓝牙模块驱动开发_stm32驱动蓝牙模块
STM32蓝牙模块驱动开发
1. 项目概述
本项目基于STM32F1系列微控制器,使用HAL库实现了蓝牙模块的驱动程序。该驱动程序通过UART接口与蓝牙模块通信,实现了蓝牙模块的初始化、AT指令发送、数据收发等功能。
项目源代码仓库:STM32_Sensor_Drives
2. 硬件连接
本项目使用的是通用蓝牙串口模块(如HC-05/HC-06等),通过UART接口与STM32连接。具体连接如下:
- 蓝牙模块TX -> STM32 PB11 (USART3_RX)
- 蓝牙模块RX -> STM32 PB10 (USART3_TX)
- 蓝牙模块VCC -> 3.3V/5V(取决于模块类型)
- 蓝牙模块GND -> GND
3. 代码结构
项目主要包含以下几个文件:
main.c
:主程序,包含系统初始化和主循环usart.c/h
:UART配置和蓝牙通信相关函数gpio.c/h
:GPIO配置
4. 关键代码分析
4.1 蓝牙模块参数定义
在usart.h
中定义了蓝牙模块的基本参数:
/******************************** Bluetooth 连接引脚定义 ***********************************/#define Bluetooth_NAME \"BT04\"#define Bluetooth_PIN \"1234\"#define Bluetooth_LADDR \"AA:BB:CC:11:22:33\"#define Bluetooth_USART_BAUD_RATE \"9600\"#define Bluetooth_USART_TX_PORT GPIOB #define Bluetooth_USART_TX_PIN GPIO_Pin_10#define Bluetooth_USART_RX_PORT GPIOB#define Bluetooth_USART_RX_PIN GPIO_Pin_11#define Bluetooth_USARTx huart3
这些定义包括蓝牙模块的名称、PIN码、MAC地址、波特率以及连接的GPIO引脚。
4.2 数据结构定义
为了处理蓝牙模块的数据收发,定义了一个数据帧处理结构体:
#define RX_BUF_MAX_LEN 256 //最大接收缓存字节数extern struct STRUCT_USARTx_Fram //串口数据帧的处理结构体{ char Data_RX_BUF [ RX_BUF_MAX_LEN ]; union { __IO uint16_t InfAll; struct { __IO uint16_t FramLength :15; // 14:0 __IO uint16_t FramFinishFlag :1; // 15 } InfBit; }Inf;};
该结构体包含一个接收缓冲区和一个信息字段,信息字段使用位域技术,包含帧长度和帧完成标志。
4.3 UART初始化
在usart.c
中,实现了UART的初始化函数:
void MX_USART3_UART_Init(void){ huart3.Instance = USART3; huart3.Init.BaudRate = 115200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); }}
这里配置了USART3,用于与蓝牙模块通信,波特率为115200,8位数据位,1位停止位,无奇偶校验。
4.4 GPIO配置
在HAL_UART_MspInit
函数中,配置了UART对应的GPIO引脚:
else if(uartHandle->Instance==USART3){ /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART3_IRQn);}
这里配置了PB10为USART3_TX,PB11为USART3_RX,并启用了USART3的中断。
4.5 标准输出重定向
为了方便调试,重定向了标准输出到UART:
int fputc(int ch, FILE *f){ if (f == stdout) // 仅处理标准输出 { HAL_UART_Transmit(current_huart, (uint8_t *)&ch, 1, 100); // 阻塞发送 if (ch == \'\\n\') // 发送\\n时自动补充\\r HAL_UART_Transmit(current_huart, (uint8_t *)\"\\r\", 1, 100); } return ch;}
同时定义了两个便捷的打印宏:
#define printf_log(...) do { \\ current_huart = &huart2; \\ printf(__VA_ARGS__); \\} while(0)#define printf_blue(...) do { \\ current_huart = &Bluetooth_USARTx; \\ printf(__VA_ARGS__); \\} while(0)
printf_log
用于向调试串口(USART2)输出日志,printf_blue
用于向蓝牙模块(USART3)发送数据。
4.6 蓝牙模块初始化
蓝牙模块的初始化函数如下:
void bluetooth_start(void){ printf_log(\"Start init buletooth\\r\\n\"); HAL_UART_Receive_IT(&Bluetooth_USARTx, &UART_TEMP_CHAR, 1); uint16_t wait_time = 5000; char temp_cmd[20]; sprintf(temp_cmd, \"%s\", \"AT+RESET\\r\\n\"); uint8_t flag = send_blue_cmd(temp_cmd, \"OK\", NULL, wait_time); // sprintf(temp_cmd, \"AT+LADDR%s\\r\\n\", Bluetooth_LADDR);// send_blue_cmd(temp_cmd, \"OK\", \"LADDR\", wait_time);// // sprintf(temp_cmd, \"AT+NAME%s\\r\\n\", Bluetooth_NAME);// send_blue_cmd(temp_cmd, \"OK\", \"NAME\", wait_time);// // sprintf(temp_cmd, \"AT+PIN%s\\r\\n\", Bluetooth_PIN);// send_blue_cmd(temp_cmd, \"OK\", \"PIN\", wait_time);// // sprintf(temp_cmd, \"AT+BAUD%s\\r\\n\", Bluetooth_USART_BAUD_RATE);// send_blue_cmd(temp_cmd, \"OK\", \"BAUD\", wait_time); printf_log(\"Start init success\\r\\n\");}
该函数首先启用UART接收中断,然后发送AT+RESET命令重置蓝牙模块。注释部分是设置蓝牙模块的MAC地址、名称、PIN码和波特率的命令,可以根据需要取消注释。
4.7 AT指令发送函数
uint8_t send_blue_cmd(char* cmd, char* replay1, char* replay2, uint16_t wait_time){ printf_log(cmd); printf_blue(cmd); HAL_Delay(wait_time); if (replay1 == NULL && replay1 == NULL) return 1; char temp_buffer[RX_BUF_MAX_LEN]; read_uart_buffer(temp_buffer); if (temp_buffer != NULL) printf_log(temp_buffer); if(strstr(temp_buffer, replay1) != NULL || strstr(temp_buffer, replay2) != NULL) return 1; else printf_log(\"FAIL: Start init buletooth_%s\\n\", cmd); return 0;}
该函数用于发送AT指令并等待响应。它首先打印并发送命令,然后等待指定时间,读取响应缓冲区,检查是否包含预期的响应字符串。
4.8 数据发送函数
void blue_send_msg(char *msg){ HAL_UART_Transmit(&Bluetooth_USARTx, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);}
这是一个简单的数据发送函数,用于向蓝牙模块发送数据。
4.9 数据接收缓冲区读取函数
void read_uart_buffer(char* temp_buffer){ if (buletooth_Fram_Record.Inf.InfBit.FramFinishFlag != 1) return; strcpy(temp_buffer, buletooth_Fram_Record.Data_RX_BUF); memset(buletooth_Fram_Record.Data_RX_BUF, 0, RX_BUF_MAX_LEN); buletooth_Fram_Record.Inf.InfBit.FramLength = 0; buletooth_Fram_Record.Inf.InfBit.FramFinishFlag = 0;}
该函数用于读取接收缓冲区的数据。如果帧完成标志为1,则将数据复制到临时缓冲区,并清空接收缓冲区。
4.10 UART接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart == &Bluetooth_USARTx) { if (buletooth_Fram_Record.Inf.InfBit.FramLength < (RX_BUF_MAX_LEN - 1)) buletooth_Fram_Record.Data_RX_BUF[buletooth_Fram_Record.Inf.InfBit.FramLength++] = UART_TEMP_CHAR; if (HAL_UART_GetState(&Bluetooth_USARTx) == HAL_UART_STATE_READY) { if (buletooth_Fram_Record.Data_RX_BUF[buletooth_Fram_Record.Inf.InfBit.FramLength-1] == \'}\'){ buletooth_Fram_Record.Data_RX_BUF[buletooth_Fram_Record.Inf.InfBit.FramLength] = \'\\0\'; printf_log(\"uart back %d: %s\\r\\n\", buletooth_Fram_Record.Inf.InfBit.FramLength, buletooth_Fram_Record.Data_RX_BUF); buletooth_Fram_Record.Inf.InfBit.FramFinishFlag = 1; } } HAL_UART_Receive_IT(&Bluetooth_USARTx, &UART_TEMP_CHAR, 1); }}
这是UART接收中断的回调函数。当接收到一个字符时,将其存入接收缓冲区。如果接收到’}\'字符,则认为一帧数据接收完成,设置帧完成标志,并重新启用接收中断。
4.11 主程序
int main(void){ /* 省略初始化代码 */ MX_GPIO_Init(); MX_USART2_UART_Init(); MX_USART3_UART_Init(); /* USER CODE BEGIN 2 */ printf_log(\"\\r\\n/**********STARTING SYSTEM**********/\\r\\n\"); bluetooth_start(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { blue_send_msg(\"hello\\n\"); char temp_buffer[RX_BUF_MAX_LEN] = {0}; read_uart_buffer(temp_buffer); if (strlen(temp_buffer) != 0) printf_log(\"main %d :%s\\r\\n\", strlen(temp_buffer), temp_buffer); //memset(temp_buffer, 0, sizeof(temp_buffer)); HAL_Delay(500); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */}
主程序初始化GPIO和UART,启动蓝牙模块,然后在主循环中每500ms发送一次\"hello\"消息,并读取接收缓冲区的数据。
5. 使用方法
- 将蓝牙模块按照硬件连接部分所述连接到STM32
- 编译并下载程序到STM32
- 使用手机蓝牙连接到蓝牙模块(名称为BT04,PIN码为1234)
- 使用蓝牙串口工具发送和接收数据
6. 注意事项
- 本驱动程序使用的是USART3,如需更改,请修改
Bluetooth_USARTx
宏定义 - 蓝牙模块的默认波特率为115200,如需更改,请修改
MX_USART3_UART_Init
函数中的波特率设置 - 接收数据帧的结束标志为’}\'字符,如需更改,请修改
HAL_UART_RxCpltCallback
函数 - 如需配置蓝牙模块的名称、PIN码等参数,请取消
bluetooth_start
函数中的注释
7. 扩展功能
本驱动程序可以扩展以支持更多功能,例如:
- 添加蓝牙连接状态检测
- 实现蓝牙数据的解析和处理
- 添加蓝牙低功耗模式支持
- 实现蓝牙配对和安全认证
8. 参考资料
- STM32F1 Reference Manual
- STM32 HAL Library Documentation
- HC-05/HC-06 Bluetooth Module Datasheet