当前位置: 首页 > news >正文

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 ConfigurationPB10     ------> USART3_TXPB11     ------> 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时自动补充\rHAL_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. 使用方法

  1. 将蓝牙模块按照硬件连接部分所述连接到STM32
  2. 编译并下载程序到STM32
  3. 使用手机蓝牙连接到蓝牙模块(名称为BT04,PIN码为1234)
  4. 使用蓝牙串口工具发送和接收数据

6. 注意事项

  1. 本驱动程序使用的是USART3,如需更改,请修改Bluetooth_USARTx宏定义
  2. 蓝牙模块的默认波特率为115200,如需更改,请修改MX_USART3_UART_Init函数中的波特率设置
  3. 接收数据帧的结束标志为’}'字符,如需更改,请修改HAL_UART_RxCpltCallback函数
  4. 如需配置蓝牙模块的名称、PIN码等参数,请取消bluetooth_start函数中的注释

7. 扩展功能

本驱动程序可以扩展以支持更多功能,例如:

  1. 添加蓝牙连接状态检测
  2. 实现蓝牙数据的解析和处理
  3. 添加蓝牙低功耗模式支持
  4. 实现蓝牙配对和安全认证

8. 参考资料

  • STM32F1 Reference Manual
  • STM32 HAL Library Documentation
  • HC-05/HC-06 Bluetooth Module Datasheet
http://www.dtcms.com/a/325413.html

相关文章:

  • 什么是结构化思维?什么是结构化编程?
  • 获取MaixPy系列开发板机器码——MaixHub 模型下载机器码获取方法
  • 【Python】在rk3588开发板排查内存泄漏问题过程记录
  • 视频前处理技术全解析:从基础到前沿
  • DreaMoving:基于扩散模型的可控视频生成框架
  • 安全合规4--下一代防火墙组网
  • GaussDB 数据库架构师修炼(十三)安全管理(1)-账号的管理
  • vue+flask基于规则的求职推荐系统
  • CentOS7搭建安全FTP服务器指南
  • 【安全发布】微软2025年07月漏洞通告
  • C语言如何安全的进行字符串拷贝
  • MQTT:Vue集成MQTT
  • GaussDB安全配置全景指南:构建企业级数据库防护体系
  • 【vue(一))路由】
  • uncalled4
  • 昆仑万维SkyReels-A3模型发布:照片开口说话,视频创作“一键改台词”
  • 使用行为树控制机器人(二) —— 黑板
  • 哈希、存储、连接:使用 ES|QL LOOKUP JOIN 的日志去重现代解决方案
  • Logistic Loss Function|逻辑回归代价函数
  • 实习学习记录
  • 集成电路学习:什么是URDF Parser统一机器人描述格式解析器
  • ttyd终端工具移植到OpenHarmony
  • 工业相机与智能相机的区别
  • 5G与云计算对代理IP行业的深远影响
  • 用 Python 绘制企业年度财务可视化报告 —— 从 Excel 到 9 种图表全覆盖
  • nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)
  • 论文中PDF的公式如何提取-公式提取
  • Lightroom 安卓版 + Windows 版 + Mac 版全适配,编辑管理一站式,专业摄影后期教程
  • 【实用案例】录音分片上传的核心逻辑和实现案例【文章附有代码】
  • 智能双行框!百度全量上线AI搜索,是革新浪潮还是昙花一现?