多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

HC05蓝牙模块+Arduino UNO:手机控制LED完整实操教程

HC05蓝牙模块+Arduino UNO:手机控制LED完整实操教程 直接说结论这是入门蓝牙硬件控制性价比最高的一条路。HC05 加一块 UNO 板载 LED整套下来不超过 30 块钱却能完整跑通“手机发指令-蓝牙透传-单片机解析-外设动作”的全链路。这篇文章我会从选型思路、接线、AT 指令配置、代码烧录到手机端调试一步步讲清楚尤其会重点说说 HC05 连不上、乱码、主从模式这些坑。适合刚接触 Arduino、想玩蓝牙控制的同学也适合想把手头 HC05 模块用起来的老手。1. 项目整体设计与思路拆解1.1 为什么选 HC05 而不是其他蓝牙方案市面上常见的蓝牙模块有 HC05、HC06、JDY-31、HM-10 这些但做手机控制外设HC05 依然是最稳妥的选择。核心原因就一个HC05 支持主从一体既能当从机被手机连接也能当主机去连接别的蓝牙设备。而 HC06 只能做从机JDY-31 虽然便宜且支持 AT 指令但兼容性和资料丰富度都不如 HC05。从成本角度算一笔账一块 HC05 模块大概 15 到 20 元UNO 板如果是兼容版也就 20 元出头板载 LED 是现成的不需要额外买硬件。相比 ESP32 的蓝牙方案HC05 的学习曲线更平缓——它不需要你理解复杂的协议栈本质上就是一个“无线串口”把 TX、RX 对接好就能用。还有一点容易被忽略HC05 的 AT 指令是标准化的。这意味着你配好一个模块后面做双机通信、主从切换、改波特率、改名称密码全都有固定套路不会因为换了商家就出现玄学差异。对于系列教程来说这种可复制性很重要。1.2 用板载 LED 做实验的科学性在哪很多同学第一次做蓝牙控制第一反应是外接一个 LED 或者继电器这其实没必要。UNO 板载的 L 口 LED 接了数字引脚 13而且引脚 13 上有板载电阻不需要额外串限流电阻直接就能用。用它做实验的最大好处是排查问题范围足够小。想清楚这个逻辑如果手机发了指令灯不亮可能性只有三种——蓝牙链路没通、串口数据没到、代码逻辑出错。如果你外接了一堆传感器和继电器问题就可能是供电不足、引脚冲突、电平不匹配。从板载 LED 起步等于把变量控制在最小范围这对新手排查问题非常友好。还有一个实际考量板载 LED 在 UNO 上电时就会有一个闪烁程序如果烧录前能看见 LED 在闪说明板子本身是好的。到烧录代码后如果 LED 不再按默认节奏闪而是被你的指令控制那说明你的整套链路已经通了。这个从“默认态”到“受控态”的转变本身就是一个天然的验证信号。1.3 这个项目能延伸到哪些场景别小看“控制一个 LED 亮灭”这件事它背后是物联网控制的最简模型。把板载 LED 换成继电器就是远程开关插座换成水泵就是远程浇花换成舵机就是远程开门。我在后面的系列文章里会逐步扩展但第一步必须先把这套链路跑稳。关于选型我再多说一句为什么不用蓝牙 4.0 的 HM-10因为 HM-10 的 BLE 协议和 Android 手机的兼容性有坑尤其是老版本 Android 手机和 iOS 设备经常出现配对成功后秒断的情况。HC05 走的是经典蓝牙 2.0 协议几乎所有手机都能稳定连接传输距离还更远实测在空旷环境下能到 10 米。做教学项目稳定性远比先进性重要。2. 硬件准备与接线实操要点2.1 物料清单与购买注意事项做这个项目你需要准备的物料非常简单但有几个细节值得说道。UNO 板建议选带有 CH340 芯片的兼容版便宜且驱动好装原版是 16U2 芯片虽然稳定性更好但价格高出好几倍对新手来说没必要。HC05 模块要注意区分“带底板”和“裸板”。带底板的版本引出了排针可以直接插面包板上面通常还带一个稳压芯片输入 5V 没问题。裸板则只有排针孔而且不带稳压供电必须是 3.6 到 6V接 5V 勉强能用但有点悬。我建议多花几块钱买带底板的省去很多麻烦。还需要一根 USB 数据线注意必须是带数据传输的线不是只有充电功能的那种。判断方法很简单插上电脑后设备管理器能识别到 COM 口就是数据线。那种只能充电的线看起来一模一样很多新手在这里卡了半天。配套的还有杜邦线若干、一个智能手机。手机端需要装一款蓝牙串口 APP我后面会专门说怎么选。2.2 模块引脚对应关系详解HC05 模块的引脚不多但接线时非常容易出错。先看背面丝印一般有六个引脚EN有的标 KEY、VCC、GND、TXD、RXD、STATE。关键点来了HC05 的 TXD 要接 UNO 的 RX引脚 0RXD 要接 UNO 的 TX引脚 1。这就是最经典的交叉接线法——发送接接收接收接发送。不理解这个的同学可以想成两个人对话A 的嘴巴必须对着 B 的耳朵如果嘴巴对嘴巴那谁都听不见谁。这里有一个新手最容易踩的坑UNO 的引脚 0 和引脚 1 在插上 HC05 后不能再用来做其他通信。因为这两个引脚是 USB 转串口芯片和主控芯片之间的通信通道你外接蓝牙模块占用了它们USB 串口就会“失效”。也就是说如果你用 HC05 占用了引脚 0 和 1烧录程序会失败除非你先拔掉 HC05 或者把 UNO 的 RX、TX 接到其他软串口引脚上。供电方面VCC 接 5VGND 接 GND。STATE 引脚是状态输出未连接时低电平连接后高电平可以用来驱动一个 LED 指示蓝牙连接状态这个引脚可以不接不影响功能。2.3 接线过程与检查方法具体接线顺序建议这样做先把 UNO 断电确保安全。用杜邦线将 HC05 的 RXD 连接到 UNO 的引脚 1TX。将 HC05 的 TXD 连接到 UNO 的引脚 0RX。VCC 接 5VGND 接 GND。连接好后仔细检查一遍尤其确认有没有接反 TX 和 RX。接好以后给 UNO 上电观察 HC05 模块上的 LED 状态。HC05 的板载 LED 通常有两种闪烁模式快闪大约 2 秒闪一次表示处于 AT 命令模式或者等待配对慢闪大约 1 秒闪一次表示已经连接上设备。如果 LED 不亮先查供电如果 LED 常亮不动也属于正常情况说明模块可能在等待配置。另一个检查方法开机后手机搜索蓝牙设备如果能搜到一个名为“HC-05”的设备说明模块供电和基本功能都正常。这时候可以先用手机配对试试密码默认是 1234 或 0000。如果手机能配对成功说明模块工作正常问题大概率在后期配置。注意给 HC05 接线的顺序很重要我建议先接 GND再接 VCC最后接 TX 和 RX。因为模块在上电瞬间如果有 GPIO 口电平抖动可能会导致误触发进入 AT 模式先接好地线和电源线能减少这种问题。3. 核心代码实现与参数配置详解3.1 两种模式的区别与切换方法HC05 有AT 命令模式和通信模式两种工作状态这是整个项目的关键。AT 模式下模块接收 AT 指令来配置参数通信模式下模块作为无线串口透传数据。区分的方法是看模块上的 LED 闪烁频率AT 模式大约 2 秒快闪一次通信模式大约 1 秒慢闪一次。进入 AT 模式有两种方式取决于你的模块是带底板还是裸板。带底板的模块上有一个按钮有的叫 EN有的叫 KEY按住按钮然后给模块上电模块就会进入 AT 模式。裸板则需要把 EN/KEY 引脚拉高到 VCC同样是在上电前拉高。如果要在不拆线的情况下进入 AT 模式还有一个办法先把蓝牙从手机上断开再短按底板上的按钮让模块进入 AT 模式。但这个方法不太稳定我建议你还是按规范来接好 EN 到 VCC 的跳线再上电。这里有个细节很多教程不会提如果你已经通过 UNO 给 HC05 供电那么进入 AT 模式需要在 UNO 上电前就把 EN 拉高。用 Arduino 代码里的delay(1000)加空闲引脚拉高也可以但那是更进阶的方案。新手就用最笨但最可靠的方法——拔掉 HC05 供电接上 EN 到 VCC 跳线再重新上电。3.2 AT 指令配置实操进入 AT 模式后你需要通过串口给 HC05 发送指令。这里的坑点在于AT 模式要求波特率是 38400而不是默认的 9600。很多新手在这里犯迷糊配了半天没反应其实只是波特率选错了。我用的是 UNO 自带的 USB 转串口功能通过 Arduino IDE 的串口监视器发送 AT 指令。具体操作如下打开 Arduino IDE选择好正确的端口在设备管理器里查看 COM 口编号。打开串口监视器波特率选 38400。在发送框中输入AT点击发送。如果返回OK说明模块在 AT 模式且通讯正常。输入ATNAMEMyBluetooth设置模块名称可选。输入ATPSWD1234设置配对密码可选不设置默认就是 1234 或 0000。输入ATUART9600,0,0将通信波特率设置为 9600这里是为了和后面代码一致。输入ATROLE0设置模块为从机模式这是手机连接模块的模式。最后给模块重新上电退出 AT 模式进入通信模式。要注意一点串口监视器如果勾选了“发送新行”默认开启会在指令末尾追加一个回车符HC05 对 AT 指令是接受回车换行的。如果取消勾选“发送新行”指令可能没反应。我试过好几次有时候明明指令没错但没返回就是因为发送框末尾没带换行。3.3 Arduino 代码开发与逐行解读模块配好后剩下的就是写 Arduino 代码了。核心逻辑非常简单初始化串口读取蓝牙发来的数据判断字符后控制板载 LED。看一下完整的示例代码// 引脚定义 const int ledPin 13; // UNO 板载 LED // 程序初始化 void setup() { // 初始化板载 LED 引脚为输出 pinMode(ledPin, OUTPUT); // 初始化串口通信波特率必须与 HC05 通信模式一致 Serial.begin(9600); // 起始状态LED 熄灭 digitalWrite(ledPin, LOW); } // 主循环 void loop() { // 检查串口是否有数据 if (Serial.available() 0) { // 读取一个字节 char cmd Serial.read(); // 字符 1 点亮 LED if (cmd 1) { digitalWrite(ledPin, HIGH); Serial.println(LED ON); } // 字符 0 熄灭 LED else if (cmd 0) { digitalWrite(ledPin, LOW); Serial.println(LED OFF); } } }这个代码里有个细节要注意Serial.begin(9600)的波特率必须和 HC05 通信模式一致。我在前面 AT 配置里特意设置了ATUART9600,0,0就是为了这一步能对得上。如果你的 HC05 模块之前被设置过其他波特率这里就要改成相应值否则收到的全是乱码。代码里的Serial.println(LED ON)这句话不是必须的但保留它对调试有帮助。它会把控制结果回传给手机你在手机 APP 里能看到反馈信息知道命令确实被执行了。烧录这个代码有个小技巧如果 HC05 已经接在了引脚 0 和 1 上直接烧录大概率会失败因为 HC05 会干扰 USB 串口通信。解决办法是先拔掉 HC05 的 TX 线或直接把 HC05 断电烧录成功后再接回去。3.4 一个进阶小技巧软串口实现同时调试如果你想让 HC05 烧录时不拔线也能工作可以用软串口方案即用 UNO 的其他数字引脚模拟串口。这样的话HC05 接在引脚 2 和 3 上引脚 0 和 1 保留给 USB 调试用。典型代码如下#include SoftwareSerial.h SoftwareSerial BT(2, 3); // RX, TX void setup() { Serial.begin(9600); BT.begin(9600); } void loop() { if (BT.available()) { char cmd BT.read(); Serial.print(cmd); if (cmd 1) { digitalWrite(13, HIGH); } else if (cmd 0) { digitalWrite(13, LOW); } } }软串口的缺点是最高波特率有限制9600 没问题28800 以上就可能丢数据。但用来做蓝牙控制足够用了。我建议新手做这个项目优先用软串口因为烧录调试方便很多不需要每次拔线。4. 手机端操作与联调实录4.1 蓝牙串口 APP 的选型问题手机端的 APP 选择没有统一标准但有几个硬性要求能连接经典蓝牙不是 BLE、能发送自定义字符串、最好能显示十六进制数据。我用过几款功能大同小异关键是别选那些只支持 BLE 的 App。建议先打开手机蓝牙搜索并配对 HC05。配对成功后再打开串口 APP连接到 HC05。有几个 APP 在配对后还需要在 APP 内建立连接这一步不能省。这里有一个常见的错误理解手机的系统蓝牙设置里显示“已配对”不等于 APP 能通信。必须让 APP 主动建立串口连接通信才会建立。如果在系统设置里配对成功但 APP 不发送数据请回 APP 检查连接状态。有些手机在连接 HC05 后会自动弹出“是否允许访问通讯录”之类的权限请求可以直接拒绝不影响蓝牙通信。如果手机提示“无法连接”建议先在系统蓝牙设置中解除配对然后在串口 APP 里重新搜索并配对连接路径不同成功率也不同。4.2 联调过程的完整操作步骤手机端配置好以后真正联调时的操作方法如下打开手机系统蓝牙搜索新设备。找到 HC05 后点击配对输入密码 1234 或 0000。配对成功后打开蓝牙串口 APP选择要连接的设备。APP 连接成功后HC05 模块的 LED 会从快闪变为慢闪有的模块是常亮表示已经建立连接。UNO 板上电代码开始运行板载 LED 处于低电平熄灭状态。在 APP 的发送框中输入1点击发送。如果一切正常板载 LED 会点亮。输入0LED 熄灭。如果以上步骤都执行了但 LED 没反应先别怀疑模块坏了按下面顺序排查。第一步看 HC05 的 LED 是否处于慢闪或常亮状态。如果不是说明蓝牙链路没通回看配对步骤。第二步确认代码烧录成功。可以打开串口监视器波特率 9600在手机上发送1如果串口监视器打印出了LED ON说明代码和串口链路都没问题问题出在手机 APP 或连接上。第三步确认手机 APP 发送的确实是字符1而不是别的。很多 APP 默认发送十六进制或带换行。如果发送的是0x31即字符 1 的十六进制那代码里的if (cmd 1)判断也能匹配上但如果发送的是文本01那就是两个字符前面的 0 会被当成命令。这个需要仔细看 APP 的设置项。4.3 实测过程中的现场记录我自己测试的时候遇到过一个问题手机发送1后 LED 亮了但再发送0没反应。排查后发现APP 里勾选了“发送新行”选项导致每次发送的内容变成0\n代码读取到字符0后本来应该执行熄灭但紧接着读到的\nASCII 10被代码忽略了问题不在换行符本身而在于我写代码时判断完0和1后没有把剩余缓冲区清空导致下一次来的1被上一次的\n挤到了缓冲后面。解决办法也很简单在loop()末尾加while(Serial.available() 0) { Serial.read(); }把缓冲区清空。这是很多新手写串口命令时容易忽略的细节。4.4 扩展玩法字符串指令解析如果只控制一个 LED用单字符1、0就够了。但如果后续要控制多个外设比如控制三个 LED、一个蜂鸣器、一个电机就需要自定义一套简单协议下面这个格式很实用#LED1_ON #LED1_OFF #BUZZER_ON然后代码里可以用Serial.readStringUntil(\n)读取一整行再做字符串匹配。这种方式更接近真实项目中的通讯协议设计一句话解释就是把手机当遥控器把指令当消息协议就是双方约定好的消息格式。为什么推荐渐进式扩展因为单字符指令实现简单适合验证链路字符串指令虽然稍微复杂但为后续项目铺路是值得的我自己的系列教程后面几篇就是基于这套字符串协议做继电器控制、温湿度上传、双机通信这些功能的。5. 常见问题排查与调试实录做蓝牙控制类的项目最让新手头疼的就是各种“连接不上”“收不到数据”的问题。这一块我把踩过的坑和排查思路整理成一套速查表按优先级排列。出现问题的排查顺序是先看模块供电和指示灯再看手机配对状态然后看 APP 连接状态接着核对串口波特率最后检查代码逻辑。顺序不能乱否则低层问题没解决就排查上层浪费时间还可能绕晕。模块 LED 不闪烁先量 VCC 和 GND 之间的电压应为 5V 左右。如果用的是裸板要注意供电不可超过 5V否则可能损坏模块。如果电压正常但 LED 不亮大概率模块本身坏了换模块测试。手机搜不到 HC05检查模块是否处于 AT 模式。AT 模式下虽然也会广播蓝牙信号但部分手机可能识别异常。另外确认模块有没有改过名字如果之前设置过一个自定义名字搜不到 HC-05 是正常的。用电脑的蓝牙再试一下可以排除手机系统问题。手机能配对但 APP 连不上这种情况多半是 APP 不支持经典蓝牙 SPI RFCOMM。换个 APP 试试或者检查 APP 权限设置在 Android 上要确保授予位置权限和附近设备权限否则系统会屏蔽蓝牙扫描和连接。还有有些 APP 在系统设置配好设备后还要点一下 APP 界面的连接按钮。发送指令没反应先确认 HC05 的 LED 是慢闪还是常亮如果是快闪说明模块不在通信模式。这个情况经常发生在刚配置完 AT 指令后模块还在 AT 模式下需要重新上电切换。其次确认 Arduino 串口波特率和 HC05 一致最常见的就是 HC05 是 115200 而你代码里写 9600。收到的数据是乱码波特率不匹配。用串口监视器连接 Arduino如果监视器输出乱码而手机发送的是英文检查 Arduino 代码里的波特率和 HC05 通信模式波特率是否一致。另外还有一种情况是 HC05 被设置了奇偶校验位ATUART 指令里第二个 0 参数可以查一下当前配置。代码烧录失败在 HC05 占用了串口引脚的情况下UNO 无法通过 USB 下载程序。拔掉 HC05 的 RX 线注意是 HC05 接 UNO 引脚 0 的那根线然后重新烧录。如果拔线不方便用软串口方案彻底避免这个问题。另外一个值得留意的小问题HC05 模块的 STATE 引脚我建议接一个 LED 做连接指示。原因很现实项目做完后放一段时间再回来玩可能忘了模块是否连上手机。用 STATE 引脚控制一个 LED亮着就是连接成功暗着就是断开省去很多排查时间的浪费。6. 基于 HC05 的下一步扩展思路6.1 从单 LED 扩展到多路控制当你掌握了 LED 控制下一步自然就是扩展外设。我推荐先做隔离型继电器控制因为继电器是电磁隔离的可以控制高压设备安全性和实用性都有了。四路继电器的接线思路和单 LED 完全一样只是多了几个引脚和对应的数字引脚定义。代码层面可以这样做char cmd; if (Serial.available()) { cmd Serial.read(); switch(cmd) { case 1: digitalWrite(4, HIGH); break; case 2: digitalWrite(5, HIGH); break; case 3: digitalWrite(6, HIGH); break; case 4: digitalWrite(7, HIGH); break; case 5: digitalWrite(4, LOW); break; case 6: digitalWrite(5, LOW); break; case 7: digitalWrite(6, LOW); break; case 8: digitalWrite(7, LOW); break; } }这样手机端就可以用数字 一个开关动作来控制多路设备。但字符太多容易记混更推荐用格式化的指令R1ON、R2OFF这样的按字母加数字组合。解析时可以用strchr定位字母位置也可以用sscanf提取数字代码写起来更清晰也能少打字符。6.2 状态反馈与上传HC05 不只是单向接收指令也可以把单片机采集到的数据发回手机。温度、湿度、传感器状态、开关状态都能通过串口回传。这个功能在物联网场景里完全够用做家用小设备不太需要完整的上云方案手机直连反而更私密更可控。回传数据的代码非常简单float temp 26.5; BT.print(TEMP: ); BT.println(temp);手机上用能显示实时串口数据的 APP就能以一定频率刷新看到传感器数据了。这一步实现了从“控制”到“数据交互”的跃迁算是蓝牙项目的第二里程碑。6.3 双机通信方案预告HC05 支持主从模式这意味着你可以用第二块 HC05 连接第一块 HC05在串口层面打通两个单片机。这个功能可以做遥控小车——主控板接手机或主 HC05从机板控制电机驱动。因为后续的系列文章二、三会专门展开讲双机通信这里不展开只提示几个关键点做主从配对时两块 HC05 必须配对即主模块的地址要指向从模块的地址。AT 指令里与地址相关的参数是绑定状态的。一旦配置错两个模块会反复搜索却无法连接常表现为 LED 一直快闪。给个经验性的参数参考主模块建议波特率 9600从模块同样 9600主模块 ROLE1从模块 ROLE0。配对指令具体如下ATROLE1 // 主模块 ATCMODE0 // 固定地址连接 ATBINDXXXX // 绑定从模块地址地址可以从从模块的ATADDR?查询获得。绑定后重新上电两个模块能看到两者 LED 同时进入慢闪状态。这个我在后续双机通信专篇里会给出完整可复现的步骤和排障记录先占个位。6.4 关于供电稳定性的一点建议做蓝牙项目供电问题往往最后才暴露。HC05 工作时峰值电流在 30 到 50mA 左右UNO 板载稳压芯片能撑住但如果你外接多个传感器或继电器USB 口的 5V 供电就可能不够。继电器吸合瞬间的电流冲击很大会让电压波动表现为蓝牙频繁断开。通常我会建议用外接 5V 2A 以上的适配器为 UNO 供电或者直接用 9V 1A 适配器插 DC 接口。电源纹波大时可以在 VCC 和 GND 之间并联一个 10V 1000uF 的电解电容和一个 104 的瓷片电容低成本能过滤大部分杂波。新手看到别人加了电容不要觉得玄学这确实是因为模块受电源干扰所迫。另外如果电机和传感器较多更科学的做法是把电源分成两路数字电路一路功率外设一路共地但不共源。很多遥控小车跑到一半蓝牙断开不是代码问题而是电机把电源拉垮了共地不共源是最直接的解决方案。7. 实操心得总结整套流程跑下来我对 HC05 这个模块的脾气算是摸清了。它的稳定性足够好前提是严格按照 AT 配置顺序来并且在烧录和通信之间做好引脚管理。很多同学做完第一遍之后会困惑为什么别人说 HC05 好用我却连不上我碰到过最多的原因其实就两个——波特率没对上或者硬件接线搞反了。从我个人的经验看做这类项目的正确姿势是先把链路最短化。所有的疑难杂症都靠“分段验证”来解决——模块本身用 AT 指令验证、手机连接用 LED 状态验证、代码执行用串口监视器验证。三段各自确认没问题后合起来就一定通。不要试图一次解决所有问题那只会让问题更难排查。还有一个小经验配置 HC05 时把 AT 模式下的波特率统一设成 38400通信模式设成 9600是经过很多项目检验过的稳妥组合。虽然 HC05 也支持到 115200但手机端很多串口 APP 对高波特率支持不完美容易丢包。9600 完全够我传指令和回传传感器数据选它纯粹是因为省心。最后再多提一句板载 LED 这个设计。看起来只是控制了个最小外设但它真正教会了你如何把一个云端概念落地到硬件。下一次做 WiFi 控制、做云端控制、做手机 APP 开发你会发现底层的套路都是一模一样的——“解析指令、驱动外设、反馈状态”这条主线永远不变。把这个最小闭环吃透后面的路会很顺。
返回列表