1. 认识HC-04蓝牙模块
第一次接触HC-04蓝牙模块时,我完全被它的小巧身材和强大功能震惊了。这个比指甲盖大不了多少的模块,居然能让我的STM32开发板和手机实现无线对话!HC-04本质上就是个"无线串口转换器",它把复杂的蓝牙通信协议封装成简单的串口操作,让我们这些嵌入式开发者不用深入研究蓝牙协议栈就能快速上手。
实测下来,HC-04的工作电压是3.3V-6V,建议直接用STM32开发板上的3.3V电源供电最稳。它的默认波特率是9600bps,这个参数后面写代码时会用到。模块上有四个关键引脚需要特别注意:VCC接电源正极,GND接地,TXD接MCU的RXD,RXD接MCU的TXD。这里最容易踩的坑就是交叉连接,我刚开始就犯过把TXD-TXD直连的错误,结果数据死活传不过去。
2. 硬件连接实战
2.1 准备材料清单
要完成这个实验,你需要准备:
- STM32最小系统板(我用的是STM32F103C8T6)
- HC-04蓝牙模块
- 杜邦线若干
- USB转TTL模块(用于调试)
- 安卓手机(安装"蓝牙串口助手"APP)
2.2 接线示意图
按照这个顺序连接绝对靠谱:
- HC-04的VCC → STM32的3.3V
- HC-04的GND → STM32的GND
- HC-04的TXD → STM32的PA10(USART1_RX)
- HC-04的RXD → STM32的PA9(USART1_TX)
这里有个实用技巧:先用USB转TTL模块测试蓝牙模块是否正常。把TTL模块的RX接HC-04的TX,TX接HC-04的RX,上电后模块指示灯应该开始慢闪,用手机搜索蓝牙设备应该能看到"HC-04"的设备名。
3. STM32串口配置
3.1 初始化USART1
我用的是HAL库,初始化代码比标准库简洁很多:
void MX_USART1_UART_Init(void) { 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; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } }3.2 中断接收配置
要实现字符回显功能,必须开启接收中断:
// 在main函数初始化部分添加 HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1){ HAL_UART_Transmit(&huart1, &rx_data, 1, 100); HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 重新开启接收 } }4. 手机端调试技巧
4.1 推荐APP选择
经过多次测试,我发现"蓝牙串口助手"和"Serial Bluetooth Terminal"这两款APP最稳定。特别是后者,支持自定义AT指令发送,调试时特别方便。
4.2 常见问题排查
如果连接后数据收发不正常,按这个顺序检查:
- 确认手机已成功配对(HC-04默认配对密码是1234)
- 检查波特率是否设置为9600
- 用逻辑分析仪抓取串口波形,确认数据是否正常传输
- 尝试降低通信速率到4800bps测试
5. 进阶功能扩展
5.1 AT指令配置
虽然HC-04默认配置就能用,但有时需要修改参数:
// 发送AT指令修改设备名 HAL_UART_Transmit(&huart1, "AT+NAMEMyHC04\r\n", 15, 100);注意每条AT指令必须以\r\n结尾。实测发现HC-04的AT模式比较特殊,需要先按住模块上的按键再上电才能进入AT模式,此时指示灯会变成快闪。
5.2 数据协议设计
实际项目中我建议定义简单的通信协议:
// 示例协议帧格式 #pragma pack(1) typedef struct { uint8_t head; // 0xAA uint8_t cmd; // 命令字 uint8_t len; // 数据长度 uint8_t data[8]; // 数据域 uint8_t checksum;// 校验和 } BLE_Frame;这样处理可以避免数据粘包问题,提高通信可靠性。我在智能家居项目中就用类似协议实现了多设备控制。
6. 性能优化建议
当传输大量数据时,建议:
- 将波特率提高到115200(需同步修改HC-04的AT参数)
- 使用DMA传输减少CPU占用
- 添加软件流控(XON/XOFF)
- 在应用层实现数据分包和重传机制
有个坑要注意:HC-04的缓冲区比较小,连续发送大量数据会导致丢包。我的解决方案是每次发送不超过20字节,并等待50ms再发下一包。
7. 项目实战案例
最近用HC-04做了个无线调试终端,分享关键代码:
// 接收处理状态机 void ProcessBLEData(uint8_t data) { static uint8_t state = 0; static BLE_Frame frame; switch(state){ case 0: // 等待帧头 if(data == 0xAA) state++; break; case 1: // 获取命令字 frame.cmd = data; state++; break; // ...其他状态处理 default: state = 0; } }这个方案成功实现了STM32与手机的双向通信,传输稳定性明显提升。整套代码我已经开源在GitHub上,包含完整的工程文件。