1. 蓝牙模块选型与硬件连接
在51单片机项目中实现蓝牙通信,HC-05和HC-06是最常用的两种模块。实测下来,HC-05更适合需要主从切换的场景,而HC-06作为从机模块价格更实惠。我经手过的智能花盆、仓库温湿度监测等项目都用过这两种模块,稳定性都没问题。
硬件接线记住一个口诀:交叉连接,共地优先。具体来说:
- 蓝牙模块的TX接单片机的RX(P3.0)
- 蓝牙模块的RX接单片机的TX(P3.1)
- 两边的GND引脚必须相连
- VCC接5V或3.3V取决于模块版本(新版HC-05通常支持3.3V)
有个容易翻车的地方:早期买的HC-05模块可能默认波特率是38400,而51单片机常用9600。这时候需要先用USB转TTL工具,通过AT命令修改蓝牙模块波特率。具体操作是给模块KEY引脚接高电平上电,进入AT模式后发送:
AT+UART=9600,0,02. 串口通信基础配置
51单片机的串口配置就像给快递站设置收发规则。TMOD寄存器相当于选择快递车类型(模式2是自动重装定时器),TH1/TL1是规定发车频率(波特率),SCON则是设置收发规则。
这里给出个万能配置模板,适合大多数51芯片:
void UartInit() { TMOD |= 0x20; // 定时器1模式2 TH1 = 0xFD; // 9600波特率@11.0592MHz TL1 = TH1; PCON &= 0x7F; // 波特率不倍增 SCON = 0x50; // 模式1+允许接收 ES = 1; // 开串口中断 EA = 1; // 开总中断 TR1 = 1; // 启动定时器 }遇到过最头疼的问题是通信乱码,通常有三个排查方向:
- 检查晶振频率是否匹配代码设置(11.0592MHz最准)
- 用逻辑分析仪抓波形看实际波特率
- 确认双方停止位、校验位设置一致
3. 数据格式转换与传输
直接发送浮点数就像把大象装进快递箱——必须拆解成零件。这里分享三种实用方法:
3.1 联合体转换法
union { float f_val; unsigned char bytes[4]; } float_union; float_union.f_val = 3.14159; for(int i=0; i<4; i++) { SBUF = float_union.bytes[i]; while(!TI); TI=0; }3.2 sprintf格式化
char buffer[20]; float temp = 25.6; sprintf(buffer, "T:%.1fC", temp); SendString(buffer);3.3 结构体打包
#pragma pack(1) typedef struct { uint16_t id; float voltage; uint8_t status; } SensorData; #pragma pack() SensorData data; SendString((char*)&data, sizeof(data));手机端接收时要注意字节序问题。Android的BluetoothSerial库默认是大端模式,而51单片机是小端。建议在数据包头增加0xAA55作为帧起始标志。
4. 手机APP调试技巧
推荐几款实测好用的蓝牙调试APP:
- Serial Bluetooth Terminal(免费,支持图表显示)
- BLE Scanner(专业版可保存历史数据)
- Arduino Bluetooth Controller(自带控件面板)
在APP里设置接收回调时,建议添加超时处理。比如每50ms检查一次缓冲区,遇到换行符或达到最大长度就触发解析。这样可以避免数据粘包问题。
数据可视化有个小技巧:在发送数据时添加前缀标识符。例如:
printf("$TEMP%.1f#", temperature);然后在APP端用正则表达式提取:
Pattern pattern = Pattern.compile("\\$TEMP(\\d+\\.\\d+)#");调试时如果发现数据丢包,可以尝试:
- 降低波特率到4800测试
- 在关键位置添加LED状态指示
- 使用软件流控制(发送XON/XOFF)
最后提醒一个隐蔽的坑:某些手机厂商会限制后台蓝牙扫描。需要在APP设置里勾选"保持唤醒"选项,否则屏幕熄灭后可能收不到数据。