
1. 从零认识HC-06它是什么以及为什么是它如果你刚开始接触单片机或者物联网DIY想给Arduino、STM32这些板子加上无线通信功能第一个听到的名字很可能就是“HC-06”。这玩意儿在电子爱好者和学生群体里几乎成了蓝牙模块的代名词。它不像那些复杂的Wi-Fi模块需要配置网络也不像Zigbee那样有学习门槛HC-06的核心就一个字简单。简单到什么程度呢你可以把它理解成一个“蓝牙串口转换器”。它一端通过UART串口和你的单片机比如Arduino对话另一端通过蓝牙和你的手机或者电脑连接。你的单片机程序完全不用管蓝牙协议栈那些复杂的东西它只需要像往常一样通过Serial.print()发送数据HC-06就会自动把这些数据打包通过蓝牙无线发送出去反过来手机App发来的数据HC-06也会原封不动地通过串口送给单片机单片机用Serial.read()就能收到。整个过程对于开发者而言透明得就像用了一根无形的串口线。那为什么是HC-06而不是其他型号市面上常见的还有HC-05、JDY-31、ATK-HC05等等。HC-06最大的特点也是它经久不衰的原因在于它的从机Slave模式固定。它出厂就被设置为一个等待连接的从设备不能主动去搜索和连接其他蓝牙设备。这个“缺陷”恰恰是它的优势配置极其简单没有主从模式切换的烦恼价格也通常比功能更全的HC-05便宜一点。对于绝大多数“手机/电脑控制单片机”的应用场景比如蓝牙小车、智能家居开关、数据上传显示HC-06就是最直接、最经济的选择。你不需要一个模块去连接另一个模块你只需要一个乖乖等待被连接的终端。从硬件上看一个典型的HC-06模块非常小巧通常只有邮票大小。正面最显眼的是那颗蓝牙芯片早期多是英国CSR的BC417系列现在国产方案也很成熟一个LED状态指示灯以及关键的6个引脚VCC电源通常是3.3V或5V具体看模块、GND地、TXD模块发送端接单片机RXD、RXD模块接收端接单片机TXD、STATE连接状态引脚可选、EN使能引脚有些模块没有。记住TXD和RXD的交叉连接这是串口通信的基础也是新手最容易接错的地方。2. 硬件连接与供电避开第一个大坑拿到HC-06模块第一步不是写代码而是正确接线和供电。这一步看似基础但至少一半的“模块不工作”问题都出在这里。我们分几个层面来说。2.1 电压匹配3.3V还是5V这是首要问题。早期的HC-06模块大多基于3.3V逻辑电平设计其VCC供电和信号引脚TXD/RXD都只能耐受3.3V。如果你直接把它接到Arduino Uno的5V引脚和5V逻辑的串口上轻则通信不稳定重则瞬间烧毁模块。如何判断最稳妥的方法是查看模块的产品说明书或卖家提供的资料。如果找不到可以观察模块上的稳压芯片如果有一个叫AMS1117-3.3的芯片一个三端稳压器那么模块大概率是5V供电输入内部降压到3.3V给蓝牙芯片使用。这种情况下模块的VCC可以接5V但信号引脚RXD仍然是3.3V逻辑不能直接接5V单片机的TXD需要电平转换。更常见的简化版模块为了降低成本省去了这颗稳压芯片直接由蓝牙芯片工作。这种模块必须使用3.3V供电同时信号电平也是3.3V。对于Arduino Uno这种5V系统你需要一个逻辑电平转换器例如TXB0104、74HC125等或者采用电阻分压等简易方法不推荐用于稳定项目。注意一个简单的测试方法是如果你有万用表在模块未连接时测量VCC和GND引脚之间的电阻。如果阻值非常小几欧姆直接上5V很可能短路这通常意味着模块是3.3V直接供电的。安全起见对于不确定的模块先用3.3V供电测试。2.2 串口引脚交叉连接原理很简单发送端TXD要对接接收端RXD。但模块和单片机各有TXD和RXD容易绕晕。HC-06的TXD 要发送数据给单片机所以应该连接到单片机的RXD接收引脚。HC-06的RXD 要接收来自单片机的数据所以应该连接到单片机的TXD发送引脚。以Arduino Uno为例HC-06 TXD - Arduino Pin 0 (RX)HC-06 RXD - Arduino Pin 1 (TX)这里有个关键细节Arduino的Pin 0和Pin 1也是其USB串口通信的引脚。当你通过USB线给Arduino上传程序或进行串口监视时这两个引脚是被占用的。如果此时HC-06也连接在上面可能会造成数据冲突导致上传程序失败。因此最佳实践是在上传程序时暂时断开HC-06与Arduino Pin 0和Pin 1的连接或者使用SoftwareSerial库将蓝牙连接到其他数字引脚实现硬件串口USB和软件串口蓝牙的分离。2.3 供电与滤波蓝牙模块在通信瞬间电流可能达到几十毫安如果电源内阻大或纹波大可能导致模块复位或通信错误。务必确保电源稳定。如果使用3.3V供电确保你的电源如AMS1117-3.3稳压器能提供至少150mA的电流。在HC-06的VCC和GND引脚之间就近并联一个10uF~100uF的电解电容和一个0.1uF的陶瓷电容。电解电容应对低频电流波动陶瓷电容滤除高频噪声。这个简单的滤波电路能极大提高模块工作的稳定性尤其是当电机、继电器等大电流设备在同一系统中时。2.4 STATE引脚的使用很多HC-06模块引出了一个STATE引脚。这个引脚的电平状态可以反映蓝牙的连接情况未连接时为低电平0V连接成功后变为高电平通常为3.3V。你可以将这个引脚连接到单片机的某个数字输入引脚通过读取其电平来判断蓝牙是否已连接从而在程序中做出相应处理比如连接后才允许控制电机这是一个提升用户体验的好方法。3. AT命令配置让模块按你的想法工作HC-06虽然简单但也提供了一些基本的配置功能通过AT命令实现。AT命令是一种古老的、基于文本的调制解调器控制协议在这里用来设置蓝牙模块的参数。常见的设置包括修改蓝牙名称默认通常是HC-06、修改配对密码默认1234、查询波特率等。3.1 进入AT模式的关键接线与上电时序给HC-06发送AT命令必须让它进入“AT模式”。而进入AT模式的方法是第一个容易让人困惑的“坑”。不同版本、不同厂商的模块方法可能略有差异但最常见的有两种按键/使能引脚法模块上可能有一个小按钮或一个标有“KEY”或“EN”的引脚。在给模块上电之前将这个引脚通过导线连接到VCC高电平然后再接通电源。此时模块上的LED可能会慢闪比如1秒亮1秒灭这表明进入了AT模式。之后你就可以通过串口发送AT命令了。发送完命令断开KEY引脚的高电平连接重新上电模块就恢复正常的通信模式。电压法有些模块没有按键而是要求在上电时其RXD引脚接收引脚保持在一个特定的高电压通常是3.3V。你可以用杜邦线在接通电源的瞬间将模块的RXD引脚与VCC短暂触碰一下然后再连接回单片机的TXD。这需要一点手速。实操心得最稳妥的方法是查阅你手上模块的具体资料。如果找不到可以尝试第一种方法。如果模块上有按键通常就是它。进入AT模式后LED的闪烁模式会与平时不同平时快闪搜索连接后常亮这是判断是否成功进入AT模式最直观的方法。3.2 常用AT命令与通信设置进入AT模式后你需要通过一个串口工具与模块通信。你可以使用Arduino IDE的串口监视器但更推荐功能更专业的工具如Putty、CoolTerm或者SSCOM。关键点在于必须将串口工具的波特率设置为HC-06 AT模式下的通信波特率。这个波特率又是一个变量。常见出厂默认值有9600、38400或115200。如果你不知道就需要逐个尝试。在串口工具中发送纯文本“AT”不带引号如果模块回复“OK”则说明波特率匹配通信成功。一些最常用的AT命令AT 测试命令回复OK表示模块正常且处于AT模式。ATNAME? 查询当前蓝牙名称。ATNAMEname 设置蓝牙名称例如ATNAMEMyRobot。ATPIN? 查询当前配对密码。ATPINpassword 设置新密码例如ATPIN8888。ATBAUD? 查询当前通信波特率。ATBAUDnum 设置波特率。这里的num是代码1代表12002代表24003代表48004代表9600最常用5代表192006代表384007代表576008代表115200。例如ATBAUD4设置为9600。3.3 配置波特率的一致性这里有一个至关重要的细节你通过AT命令设置的波特率是模块在正常通信模式下与单片机串口通信的波特率。而你在Arduino程序中用Serial.begin(9600)初始化的波特率必须与之一致。例如你用AT命令将模块波特率设为9600ATBAUD4那么你的Arduino程序就必须是Serial.begin(9600)。如果不一致双方就无法理解对方发送的数据表现为乱码或者根本收不到数据。我的建议是将HC-06的波特率设置为9600。这是最通用、最稳定的速率对于传输控制指令、传感器数据等文本信息完全足够且对单片机时钟精度要求不高。设置好后记住这个值并在你的所有相关设备单片机程序、手机App调试终端中都统一使用这个波特率。4. 单片机端程序编写以Arduino为例硬件连好了模块也配置好了接下来就是让单片机程序与蓝牙模块对话。我们以最经典的Arduino Uno平台为例展示两种主流的编程方法。4.1 方法一使用硬件串口简单直接这是最直接的方法利用Arduino自带的硬件串口Serial。void setup() { // 初始化串口通信波特率必须与HC-06设置的波特率一致 Serial.begin(9600); // 其他初始化代码... } void loop() { // 1. 监听来自蓝牙手机的数据 if (Serial.available() 0) { char receivedChar Serial.read(); // 读取一个字节 // 处理接收到的字符例如控制LED if (receivedChar 1) { digitalWrite(LED_BUILTIN, HIGH); Serial.println(LED ON); // 通过蓝牙发送回执 } else if (receivedChar 0) { digitalWrite(LED_BUILTIN, LOW); Serial.println(LED OFF); } } // 2. 主动发送数据到蓝牙手机 // 例如读取一个传感器值并发送 int sensorValue analogRead(A0); Serial.print(Sensor: ); Serial.println(sensorValue); delay(1000); // 避免发送太快 }这段代码实现了双向通信手机发送‘1’或‘0’控制板载LED同时Arduino每秒向手机发送一次模拟引脚A0的读数。缺点如之前所述硬件串口Pin 0, Pin 1与USB编程口共享。上传程序时必须断开蓝牙模块的TXD/RXD否则会冲突。4.2 方法二使用软件串口推荐为了解决上述冲突我们可以使用SoftwareSerial库将蓝牙模块连接到任意两个数字引脚创建一个独立的软件模拟串口。#include SoftwareSerial.h // 定义软件串口RX接模块的TXDTX接模块的RXD SoftwareSerial myBluetooth(2, 3); // RX, TX void setup() { Serial.begin(9600); // 硬件串口用于USB调试输出 myBluetooth.begin(9600); // 软件串口用于蓝牙通信波特率匹配HC-06 pinMode(LED_BUILTIN, OUTPUT); Serial.println(System Ready...); } void loop() { // 监听蓝牙指令 if (myBluetooth.available() 0) { char cmd myBluetooth.read(); Serial.print(Received from BT: ); // 在USB串口监视器显示便于调试 Serial.println(cmd); if (cmd 1) { digitalWrite(LED_BUILTIN, HIGH); myBluetooth.println(Status: ON); // 通过蓝牙回复 } else if (cmd 0) { digitalWrite(LED_BUILTIN, LOW); myBluetooth.println(Status: OFF); } } // 可以通过硬件串口USB发送指令测试蓝牙 if (Serial.available() 0) { char usbCmd Serial.read(); myBluetooth.write(usbCmd); // 将USB收到的命令转发给蓝牙 } }在这个例子中蓝牙模块连接到数字引脚2和3。myBluetooth对象就是通往蓝牙的串口。我们保留了硬件Serial用于通过USB线在电脑上打印调试信息这是一个非常实用的技巧。你可以同时在电脑上打开串口监视器看到系统状态和从手机发来的指令极大方便了调试。4.3 数据协议与解析上面的例子是单字符命令实际应用中可能需要更复杂的指令比如“MOTOR,150,200”控制两个电机速度。这就需要设计简单的通信协议并进行解析。一种常见的方法是使用字符串分隔符。约定以换行符\n作为一条指令的结束。String inputString ; // 用于存储接收到的字符串 bool stringComplete false; // 标志是否收到完整指令 void loop() { // 持续读取蓝牙数据 while (myBluetooth.available()) { char inChar (char)myBluetooth.read(); if (inChar \n) { // 如果收到换行符说明指令结束 stringComplete true; } else { inputString inChar; // 否则将字符添加到字符串 } } // 如果收到完整指令 if (stringComplete) { Serial.print(Command: ); Serial.println(inputString); // 解析指令 if (inputString.startsWith(MOTOR)) { // 找到逗号分隔符 int firstComma inputString.indexOf(,); int secondComma inputString.indexOf(,, firstComma 1); if (firstComma ! -1 secondComma ! -1) { int speedA inputString.substring(firstComma 1, secondComma).toInt(); int speedB inputString.substring(secondComma 1).toInt(); // 调用控制电机的函数 setMotorSpeed(speedA, speedB); myBluetooth.println(MOTOR SET OK); } } // 清空字符串准备接收下一条指令 inputString ; stringComplete false; } }这种方式的容错性比单字符好可以传输更丰富的信息。在手机App端发送指令时在末尾加上换行符即可。5. 手机端连接与控制App的选择与通信测试单片机端准备就绪后另一端就需要一个设备来连接和控制它。最常用的就是手机。5.1 蓝牙串口调试App对于开发和测试阶段不需要自己开发App直接在手机应用商店搜索“蓝牙串口”或“Serial Bluetooth Terminal”会有大量免费好用的调试工具。我常用的是“Serial Bluetooth Terminal” (Android) 和 “LightBlue” 或 “Serial” (iOS)。这些App核心功能类似搜索蓝牙设备、配对连接、打开一个终端界面进行收发数据。连接步骤通常是打开手机蓝牙设置搜索设备。你应该能看到你之前通过AT命令设置的蓝牙名称如MyRobot。点击配对输入密码默认1234或你修改后的密码。打开蓝牙串口App在App内选择已配对的设备MyRobot进行连接。连接成功后App的终端界面就可以发送和接收数据了。尝试发送一个‘1’看看Arduino板上的LED是否点亮同时接收区是否收到“LED ON”的回复。5.2 使用App Inventor或MIT App Inventor快速制作控制界面如果你不满足于简单的终端想有一个带按钮、滑块的控制界面但又不会Java/Kotlin或Swift开发那么MIT App Inventor是绝佳选择。它是一个图形化的在线App开发工具拖拽组件就能生成安卓App。核心步骤在界面设计器中添加ListPicker用于选择蓝牙设备、Button连接/断开、控制指令、Label显示状态、Slider调节速度等组件。在逻辑设计器块编辑模式中使用BluetoothClient组件。它的核心块包括BluetoothClient.AddressesAndNames 获取已配对设备列表。BluetoothClient.Connect 连接指定地址的设备。BluetoothClient.SendText 发送文本数据就是我们单片机程序能解析的指令如“MOTOR,150,200”。BluetoothClient.ReceiveText 接收文本数据读取单片机发来的状态信息。将按钮点击、滑块拖动等事件与SendText块连接并填入要发送的指令字符串。用App Inventor你可以在半小时内做出一个带有方向控制按钮和速度滑块的蓝牙小车控制器非常直观。它生成的App可以直接安装到安卓手机上使用。5.3 通信调试与常见问题在手机与模块通信测试时可能会遇到以下问题搜不到设备 确保HC-06已通电LED快闪。检查手机蓝牙是否已开启并尝试刷新搜索列表。有些旧款手机或iOS设备对蓝牙2.0/2.1HC-06是蓝牙2.0版本支持不佳可能无法搜索到但通常配对后可以连接。配对失败 确认输入的PIN码正确。尝试默认的“1234”或“0000”。连接后立即断开 检查单片机端的程序是否在持续、快速地通过串口发送大量数据有些低端模块或App处理不过来会导致断开。尝试降低单片机发送数据的频率。发送数据无反应 这是最常见的问题。请按以下顺序排查波特率 确认手机App内设置的通信波特率与HC-06模块、单片机程序三处完全一致通常是9600。接线 再次检查TXD/RXD是否交叉连接正确。供电 用万用表测量HC-06的VCC电压是否稳定且在允许范围内。共地 确保手机充电宝如果使用供电的系统其GND与单片机系统的GND是连接在一起的。所有通信设备必须共地。程序逻辑 在单片机程序中通过硬件串口USB打印调试信息确认程序是否运行到了数据接收和处理的部分。6. 进阶应用与稳定性优化当基础通信调通后可以考虑一些进阶应用和优化措施让你的项目更可靠、更专业。6.1 多模块通信与主从配置虽然HC-06是从机但如果你需要两个单片机之间通过蓝牙通信就需要至少一个主机模块。这时可以选用HC-05模块它可以设置为主机模式。一个典型的设置是A设备使用HC-05设为主机B设备使用HC-06从机。在HC-05的主机模式下通过AT命令ATLINKaddraddr是HC-06的蓝牙MAC地址可以主动连接HC-06之后两者就可以像有线串口一样透明传输数据了。6.2 功耗考虑HC-06作为经典蓝牙BR/EDR模块功耗相对后来的蓝牙低功耗BLE模块如HM-10要高不少不适合电池供电且需要长期待机的场景。如果项目对功耗敏感应考虑BLE模块。对于HC-06如果可能可以在单片机程序中控制其电源引脚在不需通信时彻底断电以节省电量。6.3 抗干扰与数据完整性在电机、继电器等干扰源附近无线通信容易受到干扰。除了之前提到的电源滤波还可以在软件层面增加校验。数据包结构 定义简单的数据帧例如[起始符][数据长度][数据内容][校验和][结束符]。校验和可以是数据内容所有字节的简单累加和。超时重发 对于重要的控制指令如果一段时间内没有收到对方的确认回复则自动重发。通信协议 使用更健壮的协议如SLIPSerial Line Internet Protocol或直接在应用层模仿Modbus RTU等格式。对于Arduino有现成的库如PacketSerial可以帮助你打包和解析数据包处理校验和。6.4 固件升级与版本差异需要注意的是市面上HC-06模块鱼龙混杂不同批次、不同厂商的模块其AT命令集、波特率甚至引脚定义可能有细微差别。如果你发现按照常见教程的AT命令不响应最好向卖家索要该批次模块的详细AT指令集文档。有些新版本模块甚至支持更高级的查询命令如ATVERSION查询固件版本。7. 项目实战构建一个蓝牙遥控智能小车让我们把以上所有知识点串联起来完成一个经典的实战项目——蓝牙遥控智能小车。这不仅是对HC-06应用的整合也涉及电机驱动、电源管理等综合知识。7.1 系统架构与元件清单主控 Arduino Uno R3蓝牙模块 HC-06 (Slave)电机驱动 L298N双H桥驱动模块可驱动两个直流电机电源 7.4V 2S锂电池组为电机驱动供电同时通过L298N的5V输出或独立的5V稳压模块为Arduino和HC-06供电。车体 双电机底盘套件带轮子、电机其他 杜邦线、开关、电容等。7.2 电路连接详解电源系统 这是小车稳定运行的核心。锂电池正负极接L298N的电源输入端子。L298N上的5V输出引脚如果启用可以给Arduino的VIN或5V引脚供电注意电流是否足够。更稳妥的做法是使用一个独立的5V/3.3V降压模块从电池取电单独给Arduino和HC-06供电避免电机启停对控制电路的干扰。电机驱动 L298N的两个输出通道OUT1/OUT2, OUT3/OUT4分别连接两个电机的导线。使能端ENA和ENB通过跳帽使能或接PWM引脚进行调速。控制输入端IN1~IN4连接Arduino的数字引脚如5,6,9,10。蓝牙连接 HC-06的VCC接Arduino的3.3V或5V根据模块决定GND接GNDTXD接Arduino的RXPin 0或软件串口的RX引脚如Pin 2RXD接Arduino的TXPin 1或软件串口的TX引脚如Pin 3。强烈建议使用软件串口将HC-06连接到Pin 2和Pin 3。7.3 核心控制程序逻辑程序需要完成几件事解析蓝牙指令、控制电机动作、实现调速。#include SoftwareSerial.h SoftwareSerial BT(2, 3); // RX, TX // 电机控制引脚定义 const int IN1 5; const int IN2 6; const int IN3 9; const int IN4 10; const int ENA 11; // PWM调速引脚 const int ENB 12; // PWM调速引脚 int speed 150; // 默认速度 (0-255) void setup() { Serial.begin(9600); BT.begin(9600); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); // ... 初始化其他引脚 Serial.println(Bluetooth Car Ready!); } void loop() { if (BT.available()) { char command BT.read(); Serial.write(command); // 在USB串口回显 switch(command) { case F: // 前进 moveForward(speed); break; case B: // 后退 moveBackward(speed); break; case L: // 左转 turnLeft(speed); break; case R: // 右转 turnRight(speed); break; case S: // 停止 stopCar(); break; case 0...9: // 数字字符调整速度 speed map(command - 0, 0, 9, 0, 255); BT.print(Speed set to: ); BT.println(speed); break; } } } void moveForward(int spd) { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, spd); analogWrite(ENB, spd); } // ... 实现其他moveBackward, turnLeft, turnRight, stopCar函数在手机App端你可以设计五个按钮分别发送‘F’, ‘B’, ‘L’, ‘R’, ‘S’字符再添加一个滑块将0-9的值发送给小车来调整速度。7.4 调试与优化要点电机干扰 电机启动瞬间会产生很大的反向电动势可能引起电源电压骤降导致Arduino或HC-06复位。务必在电机的两个引脚之间并联一个1040.1uF的陶瓷电容以及在电源输入端并联大容量电解电容如470uF。控制延迟 如果感觉遥控有延迟检查蓝牙串口的波特率是否可提升如改为115200同时检查单片机循环中是否有不必要的delay()。使用非阻塞的定时方式如millis()来管理发送传感器数据的任务。通信距离 HC-06的标称距离在空旷地带可达10米但在室内有墙体阻隔时会急剧下降。确保天线部分模块上的蛇形走线没有被金属物体完全遮挡。通过这个完整的项目你不仅掌握了HC-06的使用更串联起了嵌入式开发中硬件连接、电源管理、软件逻辑、无线通信和抗干扰设计等多个关键环节。HC-06就像一把钥匙帮你打开了无线控制世界的大门它的简单可靠让初学者能够快速获得正反馈而深入其背后的细节又能让你学到扎实的工程实践知识。