蓝牙串口模块通讯实战:从选型到STM32透传排错 📅 发布时间:2026/9/16 22:51:49 👁 浏览次数: 简介这是一份围绕蓝牙模块与串口通信结合的Android源码工程面向嵌入式开发者、物联网爱好者及需要快速实现无线透传的工程师。工程包含完整的项目代码与可运行APK可帮助读者理解蓝牙经典模式与BLE低功耗模式的选择、UART透传配置、设备发现与配对、连接管理、错误恢复及低功耗处理等关键环节。压缩包共879个文件约5.36MB以png图片、xml布局与配置、class编译文件、jar库、java源码、aidl接口、gradle构建脚本及APK安装包为主涵盖从源码到构建产物再到演示应用的完整链路。已有271人学习下载。通过阅读源码和对照示例可掌握串口与蓝牙桥接的数据封装、解封装流程并参考其电源管理和异常中断处理机制便于快速移植到自己的智能硬件或IoT项目中。1. 蓝牙串口模块通讯把有线串口变成无线先搞懂它在数据链路里的位置调试一块 STM32 板子需要把传感器数据实时传回电脑但现场没法拖一根 USB 线或者两台设备之间要隔几十米无线同步数据这时候最常见的做法就是加一个蓝牙串口模块。这类模块在嵌入式圈子里叫 SPP 蓝牙模块也有人叫蓝牙转串口透传模块。它做的事情很直接一端是 UART 接 MCU另一端是蓝牙射频数据从串口进经过模块内部的蓝牙协议栈发出对端设备装好蓝牙驱动后会把连接识别成一个虚拟 COM 口。也就是说你原来写的串口收发程序几乎不用改把有线连接换成两个蓝牙透传模块就能按串口语义做无线通讯。这种方案不挑 MCU只要串口数量够、电平匹配、波特率两边一致就能跑所以到今天仍然是低成本无线通讯里最省事的路子。这篇文章按硬件选型、AT 配置、MCU 透传代码、排错调试这条线走把蓝牙串口模块通讯里真正会踩的坑逐个说清楚。2. 从选型到接线SPP 蓝牙模块的参数差异和最小电路2.1 HC-05、HC-06、JDY-31三款主流模块差异点市面上常见的串口蓝牙模块以 CSR 芯片方案居多典型型号是 HC-05、HC-06以及完全兼容 HC-05/06 从机指令的 JDY-31。它们都不是传统意义上的低频 2.4G 透传而是支持 SPP 协议的经典蓝牙模块工作频段同为 2.4GHz通信距离在空旷环境下大约 10 米。选型时要抓三个点是否支持主从一体、AT 指令怎么进入、以及波特率范围。HC-05 主从一体需要引脚拉高才能进 AT 模式HC-06 只能做从机上电就是 AT 指令模式直接发指令即可JDY-31 的底板设计类似 HC-06但从机指令完全兼容 HC-05/06而且蓝牙 3.0 版本在连接稳定性上更好一些。我做项目通常优先考虑 JDY-31因为它的底板跳线和指示灯更直观调硬件时能少花点时间。参数HC-05HC-06JDY-31主从模式主从一体AT 可切换仅从机从机兼容 HC-05/06 指令蓝牙版本2.02.03.0进入 AT 模式EN 脚拉高再上电上电即 AT底板 AT 开关或兼容指令默认波特率960096009600工作电压3.6-6V3.6-6V3.6-6V对于需要两块板子自动配对再通讯的场景主从一体是硬需求HC-05 或 JDY-31 都能满足如果只做从机、由手机或电脑主动连HC-06 就够用。这里要提醒一句所谓“完全兼容”指的是 AT 指令层面兼容硬件引脚定义和底板的外围电路不一定一致买模块时要看对应型号的手册别用同一个接线图硬套。2.2 串口电平匹配TTL 和 RS232/RS485 不能混接很多从工控设备上拆出来的串口是 RS232 电平负逻辑、±12V 摆幅而蓝牙模块的 UART 引脚是 3.3V TTL 正逻辑。直接把 RS232 设备引出线接到模块上轻则电平识别不了产生乱码重则烧坏模块。正确的做法是在中间加一颗 MAX3232 做电平转换如果工业现场走的是 RS485还得再挂一个 485 收发器因为 485 是差分信号和 TTL 完全不兼容。对于板载串口是 5V TTL 的 MCU比如老款 AVR 或某些 5V 单片机模块能承受的 TXD 输入范围往往不够。按常见做法我会在 MCU 的 TXD 和模块 RXD 之间串联一个 1kΩ 电阻利用模块内部钳位二极管限制电压更可靠的是用双向电平转换芯片或者分压电路。很多人一上来就跳过这个细节结果模块偶尔能收到数据但乱码率很高用示波器一看波形高电平被拉到 5V模块内部却按 3.3V 判断。2.3 用 USB 转 TTL 模块在电脑上先点亮一个蓝牙模块配置 AT 指令之前最稳妥的做法是先把模块接到电脑上用串口调试助手确认能收发数据。你需要一个 USB 转 TTL 模块常见方案是 CH340 或 FTDI驱动名分别是 CH340、FTDI VCP。接线顺序是将 USB 转 TTL 的 TXD 接模块 RXDRXD 接模块 TXDGND 必须共地。VCC 根据模块规格接 5V 或 3.3VHC-05 等模块通常可接受 5V但推荐 3.3V避免板载稳压器发热。插上 USB 转 TTL在设备管理器里看到新增 COM 口比如 COM3。打开串口调试助手选择 COM3波特率设为 9600数据位 8停止位 1无校验、无流控。先让模块处于 AT 模式发送AT如果返回OK说明模块和电脑之间链路通了。这段过程里最容易出问题的地方是驱动。设备管理器出现黄色感叹号或者显示“barrot bluetooth adapter 驱动”之类不相关设备时先卸载重装 CH340 驱动再把 USB 线插到电脑直出的 USB 口不要插在扩展 HUB 上。另外注意有些 USB 转 TTL 的板载输出能力有限蓝牙模块搜索配对瞬间电流可能冲到几十毫安如果电压跌落会导致模块反复重启这时换一个带稳压电路的 USB 转 TTL 板或者单独用 LDO 给模块供电。2.4 底板跳线和状态指示JDY-31 的 AT 进入方式与指示灯含义JDY-31 底板一般带一个拨码开关一边是 AT 模式另一边是通讯模式拨到 AT 再接电脑直接发 AT 指令。有些兼容板没有拨码直接把 KEY 或者 EN 引脚拉高再上电。HC-05 则要求第 34 脚接高电平再上电时序错一点就进不了 AT 模式。状态指示灯的闪烁频率是关键信号慢闪表示等待连接快闪表示进入 AT 模式配对成功后常亮或双灯同时亮。不同批次板子闪烁定义略有差别但这是判断模块是否在工作状态的第一个线索。如果发现上电后灯不亮优先查 VCC 和 GND不要急着怀疑模块坏了。3. 用 AT 指令配置蓝牙模块主从模式、配对码、波特率一次调对3.1 进入 AT 指令状态HC-05 与 JDY-31 的控制脚时序配置蓝牙模块的第一步是让它进入 AT 指令状态。HC-05 必须拉高 EN 之后再给 VCC 上电顺序反了模块只会默认进入透传状态发AT会原样返回给你。JDY-31 底板通常有 AT 开关拨到 ON 再上电即可。HC-06 最简单上电后任何时刻发 AT 指令都会响应。很多开发者卡在“hc05 蓝牙模块连接不上”除了这类时序问题还有两种情况一是模块还保留着上一次的配对信息需要执行ATORGL恢复出厂设置二是使用的串口调试助手勾选了“发送新行”之外的其他选项导致没有发送回车符模块不认为这是一条完整指令。我一般建议配置前先发一个不带任何参数的AT看返回是不是OK。如果返回是一串乱码说明波特率不对如果返回包含ERROR则要检查指令末尾的换行符格式。模块 AT 指令对回车符的敏感度不太一样HC-05 系列支持AT\r\n部分新固件只认AT\r配置前先试两种。3.2 常用 AT 指令表名称、密码、波特率、角色以 HC-05 和兼容指令的 JDY-31 为参考常用 AT 指令如下指令作用示例说明AT测试通信返回 OK判断是否进入 AT 模式ATNAME设置蓝牙名称ATNAMEmyuart对端扫描时看到的设备名ATPSWD设置配对码ATPSWD1234默认是 1234长度 4 位ATUART设置串口参数ATUART115200,0,0波特率、停止位、校验位ATROLE设置主从角色ATROLE0 从机 / 1 主机仅主从一体模块支持ATBIND绑定对端地址见 3.3用于固定配对ATCMODE连接模式ATCMODE00 表示仅绑定地址连接ATORGL恢复出厂设置无参数清除所有自定义配置ATRESET软复位无参数配置后执行让参数生效参数说明ATUART的三个数字依次是波特率、停止位位数、校验位类型。停止位 0 表示 1 位1 表示 2 位校验位 0 表示无校验。这里的设置决定模块透传时使用什么串口参数而 AT 指令本身的响应速度由模块固件默认波特率决定。多数模块上电后 AT 模式固定使用 9600 响应但也有例外。如果你在 9600 下发送指令不响应可以尝试 38400这个值在部分 HC-05 固件里是 AT 模式专用波特率。改完ATUART后必须复位之后主机和从机都要用新波特率重新连接。3.3 配置一对主从模块实现开机自动配对点对点透传是最常见的场景。我配置两个模块时会这样操作先把两个模块都设为从机ATROLE0波特率都改成同一个值比如 115200。给其中一个从机发ATADDR读出它的蓝牙地址例如12:34:56:ab:cd:ef。把另一个模块设为主机ATROLE1然后发送ATBIND1234,56,abcdef地址中的冒号换成逗号。主机再执行ATCMODE0让主机只去连接绑定的地址。两个模块都发ATRESET断电重新上电。这套配置完成之后主机上电就会主动搜索绑定地址从机的状态灯会从慢闪变成常亮两边串口数据相当于一条虚拟串口线。这里最容易出错的是ATBIND的地址格式。有些固件要求ATBIND1234,56,abcdef有些则接受不带逗号的ATBIND123456abcdef。我遇到这个问题时会先发ATADDR看返回值格式返回值里用什么分隔符ATBIND就用什么分隔符。如果还想让主机自动扫描任意从机而不是绑定固定地址可以把ATCMODE设为 1但这样会带来配对安全问题也可能误连附近其他蓝牙模块。产品化设计建议始终绑定地址。3.4 配置失败后的恢复策略最让人头痛的是配置到一半模块不响应了。这时先给模块断电按住底板上的按键再上电通常可以让模块回到默认的 AT 模式。如果无效发ATORGL恢复出厂设置再按流程重新配置。HC-05 还有一个小细节如果上电时 EN 脚浮空模块可能进入透传模式而忽略 AT。检验是否进入 AT 模式的方法是发送ATVERSION看能不能读到固件版本。读到版本说明模块活着问题只是在配置流程读不到才需要考虑硬件连线。4. 用 STM32 和串口蓝牙透传最小收发代码与数据流边界4.1 SPP 透传的链路结构MCU 只看到一根虚拟串口线蓝牙串口模块对 MCU 来说就是一根 UART 外设。SPP 协议栈、射频链路、基带调度都由模块内部完成我们真正要负责的是三件事串口初始化参数与模块一致、用中断或 DMA 收发数据、处理缓冲区和丢包。不要试图在 MCU 侧实现蓝牙协议那是模块固件的工作。透传链路可以简化为MCU UART 发送 → 模块 TX 串口接收 → 蓝牙空中包 → 对端模块 → 对端 UART 输出。数据在每一段都是字节流所以只要两端波特率一致数据内容不会变。区别在于蓝牙通道有延迟和抖动当串口速率高过蓝牙吞吐量时模块内部 FIFO 会溢出这是丢包的根本原因。4.2 STM32F103 串口中断收发的最小回环代码以 STM32F103C8T6 HAL 库为例写一个最小无线回环测试把串口收到的数据原样发回用来验证蓝牙链路两端通不通。/* 串口句柄配置为 115200-8-N-1无硬件流控 */ UART_HandleTypeDef huart1; uint8_t rx_buf[128]; uint8_t rx_index 0; volatile uint8_t rx_flag 0; uint8_t temp_byte; /* 接收回调每收到一个字节就存进缓冲区 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart huart1) { rx_buf[rx_index] temp_byte; if (rx_index 128) { rx_index 0; rx_flag 1; // 缓冲区满主循环统一发送 } // 继续接收下一个字节 HAL_UART_Receive_IT(huart1, temp_byte, 1); } } int main(void) { HAL_Init(); SystemClock_Config(); // 一般是 72MHz 配置 MX_GPIO_Init(); MX_USART1_UART_Init(); // 波特率 115200 HAL_UART_Receive_IT(huart1, temp_byte, 1); while (1) { if (rx_flag) { // 把缓冲区的数据整包发回蓝牙模块 HAL_UART_Transmit(huart1, rx_buf, rx_index, 100); rx_index 0; rx_flag 0; } } }代码逻辑说明这里没有直接回发当前字符而是等缓冲区攒满后再整包发送目的是减少高频单字节发送对主循环的挤压。HAL_UART_Receive_IT的第三个参数是每次接收几个字节这里填 1表示每接到一个字节就触发一次中断处理完必须重新调用它否则中断不会再触发。HAL_UART_Transmit的最后一个参数是超时时间单位毫秒。115200 波特率下发送 128 字节大约耗时 11ms100ms 超时余量足够。参数化说明如果蓝牙模块配置成 9600必须把MX_USART1_UART_Init里的波特率同步改成 9600。默认huart1对应 PA9/PA10 引脚别接到 PA2/PA3否则数据根本不会到达蓝牙模块。工程里如果同时使用打印串口和蓝牙串口建议用两个不同的 USART避免调试日志和业务数据混在一起。4.3 透传的边界硬件流控、缓冲区大小和波特率上限蓝牙 SPP 的实际吞吐量受模块内部蓝牙版本和缓冲区大小限制。经典蓝牙 2.0 版本在 SPP 模式下实测有效吞吐大约在 100-200KB/s 左右蓝牙 3.0 的 JDY-31 会略好一些但仍远达不到串口理论速率。当串口波特率设为 921600 时数据到模块后依然会按蓝牙实际速率排队发送模块 FIFO 很快占满再多出来的数据只能丢。有硬件流控的模块可以接 RTS/CTS 通知 MCU 暂停发送但绝大多数 HC-05 兼容模块只引出了 RXD/TXD/GND没有流控线。实用建议是波特率控制在 115200 及以下单包长度不要超过 256 字节发送端加上帧间隔。如果数据量很大考虑用 DMA 加环形缓冲区把串口中断的耗时压到最低给主循环留出处理时间。这里还要区分与 RS485 的差异。RS485 是半双工总线发送前需要拉高方向控制脚蓝牙串口模块是全双工直接接 USART 的 TX 和 RX 即可不需要方向切换。如果产品里同时有蓝牙模块和 RS485注意电源走线要分开保持地线单点连接避免蓝牙射频噪声耦合进 485 差分线导致偶发误码。这是很多现场“485 通讯不稳定”的隐藏原因之一。5. 连接不上、乱码、自动掉线的排查顺序与验证技巧5.1 先查 USB 转串口再查 PC 蓝牙驱动“电脑连不上蓝牙模块”这句话里其实包含了两种不同的链路第一段是 USB 转 TTL 和模块之间的串口链路第二段是 PC 蓝牙射频到模块的空中链路。排查时先发AT如果串口助手能返回OK说明串口链路正常问题在 PC 蓝牙适配器如果AT无响应则回头查 CH340 驱动、COM 口号和 TX/RX 接线。当 PC 蓝牙适配器驱动异常比如设备管理器里出现“Bluetooth Support Service 不存在”或“蓝牙外围设备找不到驱动程序”时不影响 USB 转 TTL 的 AT 调试但会影响最终虚拟串口的建立。处理方式是先卸载异常蓝牙设备再让系统重新扫描硬件改动笔记本自带的蓝牙模块常用的是 Realtek 或 Intel 方案去官网下对应驱动即可。我把这个排查顺序固定下来串口助手发AT是否返回OK不返回查 USB 转 TTL 接线、CH340 驱动、COM 口号。手机蓝牙能否搜到模块名搜不到检查模块是否上电、AT 模式是否卡死、执行ATRESET。手机能否配对并出现蓝牙串口服务部分手机不原生支持 SPP需要装专用蓝牙串口软件。PC 蓝牙能否连接并虚拟出 COM 口没有串口则检查蓝牙适配器驱动与 SPP 服务。5.2 用逻辑分析仪或串口数据记录仪定位波特率失配收发乱码绝大多数是两端波特率不一致。当模块配的是 9600MCU 初始化却是 115200每个字节都会错位。最直接的验证是逻辑分析仪接模块 TXD抓一组数据波形测量位宽。比如发送 0x55示波器会出现 01010101 的方波一个位的时间如果刚好是 104us说明波特率是 9600。逻辑分析仪软件自带 UART 解码器在配置里选波特率就能直接解出内容。没有分析仪时可以用一个独立的 USB 转 TTL 模块从 4800 到 921600 逐档扫描看哪一档能解出可读字符串这能快速确定模块当前实际波特率。在长时稳定性测试里我还会用串口数据记录仪把两端收发数据打上时间戳保存下来对比同一个包在两端的到达时间能从时间差判断蓝牙链路是否存在明显抖动。5.3 低电量掉线和自动重连的配置策略模块掉线重连主要和配对模式及电源稳定性相关。电池供电时蓝牙模块发射瞬间电流可能冲到几十毫安如果电源线压降过大模块电压跌出工作范围会直接断开。解决方法是在模块电源引脚就近加一颗 100uF 电解电容和一颗 0.1uF 陶瓷电容。重连策略上主机模块在配对失败后一般会持续扫描只要从机处于可发现状态会自动回连。如果发现需要手动按键才能重连可以把ATCMODE设为 0 并重新绑定对端地址。对低功耗产品我习惯让模块平时断电需要通讯时 MCU 通过 MOS 管给模块上电再用主机模式主动发起连接握手成功后进入透传状态这样既能省电又能避开长期待机后模块内部状态机卡死的隐患。本文还有配套的精品资源点击获取