1. 项目概述从串口到蓝牙的桥梁如果你手头有一个单片机项目需要把传感器数据无线发送到手机或者想用手机App控制一个小设备蓝牙低功耗BLE几乎是绕不开的技术。但一提到BLE开发很多人第一反应是头大——要啃蓝牙协议栈、理解GATT、编写复杂的配对和连接代码光是环境搭建就能劝退不少人。我自己在几年前做第一个可穿戴设备原型时就深有体会。当时为了把心率数据从STM32发到手机折腾了整整两周的蓝牙协议。直到后来遇到了像Adafruit Bluefruit LE Friend这样的模块才意识到原来BLE开发可以如此“偷懒”。这个模块的核心思想非常巧妙它把复杂的BLE协议栈和射频部分全部封装在一块小小的板子上对外只暴露一个最古老、最通用的接口——串口UART。你不需要懂任何蓝牙GATT服务的细节只需要像操作传统的串口Wi-Fi模块一样通过发送AT命令字符串就能完成蓝牙广播、连接、数据收发等一系列操作。简单来说Bluefruit LE Friend就是一个“蓝牙转串口”的透明桥。在数据模式下你从单片机串口TX引脚发送的任何字节都会原封不动地通过蓝牙无线传输到已连接的手机App例如Nordic的nRF UART反之手机App发送的数据也会从模块的RX引脚输出让你的单片机轻松接收。而在命令模式下你可以通过一套扩展的AT指令集精细地控制模块的几乎所有行为比如修改设备名称、调整广播参数、模拟键盘鼠标HID设备甚至创建自定义的GATT服务。这种设计将开发难度从“射频协议工程师”级别降到了“会用串口发送字符串”的级别非常适合创客、嵌入式爱好者以及需要快速验证产品原型的硬件工程师。本指南将基于我多年使用此类模块的经验不仅带你走通从开箱到双向通信的完整流程更会深入拆解AT命令背后的工作原理、分享实际项目中积累的配置技巧和避坑心得。无论你是想做一个通过手机遥控的智能小车还是将温湿度数据上传到手机的监测器这篇文章都能为你提供一套即拿即用的解决方案。2. 硬件解析与初始配置2.1 模块版本识别与核心硬件布局Adafruit Bluefruit LE Friend 主要有三个硬件版本选对版本关系到你能使用的功能和固件。我手头经典型号是v2.0黑色PCB版它采用FTDI FT231X作为USB转串口芯片板载一个标准的10针SWD调试接口方便高级用户刷写自定义固件。而目前市面上主流的是v3.0版为了成本优化将USB桥接芯片换成了CP2104并移除了SWD接口。对于绝大多数仅使用AT命令进行应用开发的用户来说v3.0完全够用且更便宜。最老的v1.0蓝色PCB版内存较小已不推荐使用。拿到模块后首先认识板上的几个关键部件这对后续调试至关重要模式选择开关位于USB口附近拨向“CMD”进入命令模式拨向“UART”进入数据模式。这是整个模块功能切换的物理开关。TXD/RXD状态LED两个小灯分别对应串口数据的发送和接收。当你通过USB向模块发送数据时TXD灯会闪烁模块收到来自蓝牙的数据时RXD灯会闪烁。这是判断数据流是否正常的最直观依据。DFU模式按钮按住此按钮再插入USB模块会进入固件升级模式此时可以通过手机App进行无线固件更新。模式指示灯LED用于指示当前工作模式。快速闪烁两次停顿三秒循环往复表示处于数据模式快速闪烁三次停顿三秒则表示处于命令模式。如果LED以恒定频率快速闪烁则说明进入了DFU模式。连接状态LED当模块与手机等中心设备成功建立蓝牙连接后此蓝色LED会常亮。断开连接则会熄灭。这是判断连接状态的最重要标志。实操心得很多新手第一次使用时会忽略模式指示灯。务必牢记“闪2下是UART闪3下是CMD”。如果发现发送AT命令没反应第一件事就是检查这个灯的闪烁模式大概率是开关拨错了位置。2.2 驱动安装与串口终端配置模块需要通过USB与电脑通信因此第一步是安装正确的USB转串口驱动。对于v3.0 (CP2104芯片)你需要安装Silicon Labs的CP210x USB转UART桥接器驱动。去Silicon Labs官网下载最新的VCP驱动程序即可。对于v1.0/v2.0 (FTDI芯片)你需要安装FTDI的FT231X驱动。可以从FTDI官网下载。安装完成后将模块插入电脑USB口在设备管理器中应该能看到一个新的COM端口Windows或/dev/tty.usbserial-*设备macOS/Linux。接下来需要一个串口终端软件。我个人的选择是WindowsTera Term。免费、开源、功能强大。macOS/LinuxCoolTerm或直接使用命令行工具如screen、minicom。无论使用哪种软件串口参数必须严格设置如下波特率9600数据位8停止位1校验位无流控制硬件流控 (RTS/CTS)必须启用注意事项“硬件流控”是很多新手会栽跟头的地方。BLE模块内部缓冲区很小如果电脑发送数据过快而蓝牙链路传输较慢数据就会丢失。启用硬件流控后模块可以通过RTS/CTS信号线告诉电脑“暂停发送”从而避免数据溢出。在Tera Term中需要在“设置 串口端口”中勾选“RTS/CTS”在CoolTerm中需要在“Options Flow Control”中选择“Hardware”。配置完成后打开串口连接。先将模式开关拨到“CMD”观察模式指示灯是否为“三闪一停”。然后在终端里输入AT并回车如果模块回复OK恭喜你通信链路已经建立。3. AT命令集深度解析与应用AT命令是控制模块的灵魂。Adafruit为其BLE模块设计了一套丰富且逻辑清晰的命令集远超简单的“蓝牙串口”范畴。理解其语法和分类能让你真正释放模块的潜力。3.1 AT命令语法与四种操作模式Bluefruit LE的AT命令遵循经典的Hayes命令集风格但更加规整。每条命令都有四种可能的操作模式通过后缀来区分测试命令 (?)用于查询某个命令是否存在或获取其参数格式。例如ATBLEPOWERLEVEL?会返回OK表示该命令可用如果命令不存在则返回ERROR。在编写自动配置脚本时先用测试命令探路是个好习惯。写命令 (参数)用于设置参数。这是最常用的模式。例如设置发射功率为-8dBmATBLEPOWERLEVEL-8。如果参数合法返回OK非法则返回ERROR。执行命令 (无后缀)用于触发一个动作该动作不需要或已预设参数。例如执行系统复位ATZ或进入DFU模式ATDFU。读命令 (?)用于读取当前配置或状态。例如读取当前发射功率ATBLEPOWERLEVEL?会返回类似-4\r\nOK的结果。核心原理这种设计将“查询”、“设置”、“执行”清晰地分离开使得命令集非常易于被机器解析也便于开发者编写稳定的控制程序。你几乎可以像操作一个字典或键值对数据库一样操作这个模块。3.2 基础与硬件控制命令实战让我们从最基础的命令开始这些命令是你与模块交互的基石。ATI(识别信息)这是你的“健康检查”第一命令。输入ATI你会得到类似下面的信息BLEFRIEND nRF51822 QFAAG00 FB462DF92A2C8656 0.7.7 0.7.7 Feb 24 2015 S110 8.0.0, 0.0 OK这七行信息依次是板卡名称、蓝牙SoC型号、唯一序列号、核心库版本、固件版本、编译日期、SoftDevice版本和Bootloader版本。每次拿到新模块先用ATI确认固件版本因为不同版本支持的命令可能有差异。ATE(回显控制)ATE1开启本地回显你输入的字符会在终端显示两次一次是你打的一次是模块回的。ATE0则关闭回显。在编写单片机程序自动发送AT命令时务必关闭回显(ATE0)否则你会收到额外的字符干扰解析。(动态模式切换)这是一个非常实用的技巧。你不需要每次都去拨动物理开关。在数据模式下发送\r\n注意要有回车换行模块会切换回命令模式并回复OK。再次发送\r\n则切回数据模式。你可以用ATMODESWITCHEN命令来配置是否允许从蓝牙侧手机也通过切换模式默认是禁止的以防手机App误操作。硬件访问命令模块暴露了部分MCU的硬件功能这在调试时非常有用。ATHWGPIO可以读取或设置GPIO引脚电平。例如ATHWGPIO14,1设置引脚14为高电平。但要注意很多引脚已被模块内部功能占用如LED、按钮乱设可能导致异常。使用前最好查阅原理图。ATHWADC读取指定ADC通道的值。例如ATHWADC0读取通道0的ADC值0-255或0-1023取决于ADC分辨率配置。ATBAUDRATE谨慎使用可以修改串口波特率。虽然支持最高1Mbps但nRF51的UART性能有限在高速率下极易丢包。对于稳定的BLE UART透传强烈建议保持默认的9600波特率。如果你确实需要更改记住修改后终端软件的波特率设置也要同步更改。3.3 BLE核心功能配置GAP与连接管理GAP通用访问配置文件负责设备的广播、扫描和连接。这部分命令决定了你的设备如何被外界发现和连接。ATGAPDEVNAME(设置设备名称)这是手机扫描时看到的名称。ATGAPDEVNAMEMySensor即可修改。名称不宜过长建议在10个字符以内。ATGAPINTERVALS(设置广播参数)这个命令直接影响功耗和连接速度。格式为ATGAPINTERVALS广播间隔,最小连接间隔,最大连接间隔,从设备延迟,连接超时。广播间隔单位0.625ms。设得太短如ATGAPINTERVALS32,40,40,0,500广播间隔20ms功耗高但手机能更快发现设得太长如ATGAPINTERVALS1600,40,40,0,500间隔1秒省电但手机可能需要多等一会儿才能扫到。平衡点通常在100-500ms之间。连接间隔连接建立后主从设备通信的时间间隔。间隔越小如7.5ms实时性越高但功耗也越大间隔越大如1s越省电但数据延迟明显。ATGAPINTERVALS,,80,160,表示连接间隔在50ms到100ms之间手机中央设备会在这个范围内协商一个具体值。ATGAPSTARTADV/ATGAPSTOPADV(启停广播)ATGAPSTARTADV开始广播模块可被扫描到ATGAPSTOPADV停止广播进入低功耗状态如果未连接。一个常见误区停止广播并不会断开现有连接已连接的设备依然可以通信。要断开连接需要使用ATGAPDISCONNECT。ATBLEGETPEERADDR/ATBLEGETRSSI在连接建立后可以分别用于获取已连接对端设备的蓝牙MAC地址和接收信号强度指示。RSSI值对于粗略估算距离或信号质量很有帮助。3.4 数据通道的基石BLE UART服务模块内置了一个最重要的服务UART服务。这就是实现“蓝牙串口透传”功能的核心。服务原理模块在GATT服务器中创建了一个UART服务包含两个特征值TX特征 (UUID: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E)属性为Write或Write Without Response。手机向这个特征写入数据模块通过串口RX引脚输出。RX特征 (UUID: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E)属性为Notify。当模块从串口TX引脚收到数据时会通过这个特征以通知的方式发送给手机。 这是一种非常高效的设计利用了BLE的“通知”机制手机无需轮询模块有数据就推送给手机。相关AT命令ATBLEUARTFIFO查询UART FIFO先入先出缓冲区中当前积压的字节数。在调试数据吞吐量时有用。ATBLEUARTTX和ATBLEUARTRX这两个命令主要用于调试。在命令模式下你可以用ATBLEUARTTXHello模拟从串口收到“Hello”数据并检查手机端是否能收到通知反之ATBLEUARTRX可以读取从手机发来但尚未被取走的数据在数据模式下这些数据会直接输出到串口。与手机App通信实战将模式开关拨到UART模式灯闪2下。打开手机上的nRF Connect或nRF UARTApp。扫描并连接名为“UART”的设备。连接成功后模块的连接状态LED常亮。在手机App的UART界面发送“Hello”你会在电脑的串口终端上看到“Hello”。在电脑的串口终端里输入“World”手机App上会立刻显示“World”。这个过程完美演示了双向透传。对于你的单片机项目只需将单片机的串口TX、RX、GND与模块对应引脚连接单片机代码就完全像在与另一个串口设备通信无需任何蓝牙代码。4. 高级功能与自定义服务开发4.1 模拟HID设备键盘与鼠标这是Bluefruit LE Friend一个非常有趣且实用的功能。你可以让它模拟成一个蓝牙键盘或鼠标直接控制电脑或手机。这在制作自定义遥控器、演示器或无障碍设备时特别有用。启用HID首先需要启用HID服务。ATBLEHIDEN1开启HID总开关。ATBLEKEYBOARDEN1单独启用键盘功能ATBLEHIDMOUSEEN1启用鼠标功能。发送按键单个按键ATBLEKEYBOARDchar例如ATBLEKEYBOARDA发送字母A。组合键需要用到修饰键值和键盘扫描码。例如发送CtrlCATBLEKEYBOARDCODE02,00,00,00,00,00,06,00,00,00,00,00,00,00,00,00这个16字节的数组里第一个字节02代表左Ctrl键按下第六个字节06代表字母C的HID使用页扫描码。释放按键需要发送全零的数组。实际操作中我强烈建议不要手动拼写这个数组而是利用Adafruit提供的Arduino或Python库来生成它们有友好的封装函数。控制鼠标ATBLEHIDMOUSEMOVEx,y,wheel移动鼠标指针。x, y为相对移动量-127 到 127wheel为滚轮移动量。ATBLEHIDMOUSEBUTTONbuttons控制鼠标按键。buttons是一个位掩码1左键2右键4中键。 例如ATBLEHIDMOUSEMOVE10,0,0让指针右移10个单位ATBLEHIDMOUSEBUTTON1点击左键。避坑指南模拟HID设备时连接间隔对体验影响巨大。如果连接间隔设得太大如500ms鼠标移动会感到明显的卡顿。建议将连接间隔设置为最小值如7.5ms以获得流畅体验但这会显著增加功耗。4.2 创建自定义GATT服务与特征值虽然内置的UART和HID服务覆盖了大部分应用但有时你需要传输特定结构的数据如传感器三轴数据或者需要符合某个标准的蓝牙设备配置文件。这时就需要创建自定义GATT服务。模块提供了ATGATTADDCHAR和ATGATTCHAR等命令来动态构建服务。但请注意在Bluefruit LE Friend上自定义GATT服务是存储在RAM中的断电即丢失。每次上电都需要重新配置。这对于固定功能的产品原型来说可能不够方便但对于动态配置和测试来说足够了。创建一个简单的心率测量服务示例清除现有服务ATGATTCLEAR添加心率服务心率服务的标准UUID是0x180D。ATGATTADDSERVICE0x180D添加心率测量特征该特征UUID为0x2A37属性为Notify服务器主动通知客户端。ATGATTADDCHAR0x2A37,0x100x10代表Notify属性添加身体传感器位置特征UUID为0x2A38属性为Read。ATGATTADDCHAR0x2A38,0x020x02代表Read属性设置身体传感器位置值假设是手腕佩戴值为3。ATGATTCHAR2,3假设这是添加的第二个特征索引从1开始开始广播ATGAPSTARTADV现在用手机上的nRF ConnectApp扫描并连接你的设备就能在服务列表中看到标准的“Heart Rate”服务并能读取传感器位置以及订阅心率测量通知。你可以通过ATGATTCHAR1,value假设心率测量是第一个特征来模拟发送一个心率值例如0x40代表64 BPM手机App会立刻收到通知。这个过程虽然需要手动输入多条AT命令但它清晰地揭示了BLE设备是如何通过GATT组织数据的。对于量产产品这些配置通常会编译进固件一劳永逸。4.3 Beacon功能与空中升级iBeacon/Eddystone模拟模块可以配置为广播iBeacon或Eddystone格式的帧变成一个蓝牙信标。这对于室内定位或信息推送应用很有用。命令如ATBLEBEACON可以设置UUID、Major、Minor值和发射功率校准值。设置后模块会持续广播信标帧任何支持信标扫描的App如手机上的“蓝牙扫描器”都能接收到。空中升级这是Adafruit模块的一大亮点。当有新固件发布时你无需任何硬件编程器。让模块进入DFU模式按住DFU按钮插入USB或发送ATDFU命令。模式指示灯会变成快速恒定的闪烁。在手机上安装Adafruit Bluefruit LE ConnectApp。打开App它会自动搜索处于DFU模式的设备。选择设备App会从Adafruit服务器获取可用的固件列表选择并开始升级。 整个过程无线完成非常方便。升级前务必确保设备电量充足升级过程中不要断开蓝牙连接。5. 实战项目构建一个智能环境监测器让我们综合运用以上知识构建一个实际项目一个通过BLE将温湿度数据发送到手机的环境监测器。5.1 系统架构与硬件连接核心控制器我们使用一块常见的开发板如Arduino Uno或ESP32。这里以Arduino为例。传感器DHT22温湿度传感器。BLE模块Adafruit Bluefruit LE Friend。连接方式Arduino 5V - BLE Friend VINArduino GND - BLE Friend GNDArduino TX (Pin 1) - BLE Friend RXArduino RX (Pin 0) - BLE Friend TXDHT22 Data Pin - Arduino Digital Pin 2重要提示Arduino Uno的Pin 0和1也是串口监视器的端口。当BLE模块连接后会占用此硬件串口导致你无法通过USB打印调试信息。在最终部署时这没问题但在开发调试阶段建议使用SoftwareSerial库将BLE模块连接到其他数字引脚如Pin 10为RXPin 11为TX以便保留主串口用于调试输出。5.2 Arduino端代码逻辑与AT命令发送Arduino代码的核心是初始化串口、配置BLE模块、读取传感器数据并通过串口将数据发送给BLE模块模块在UART模式下会自动转发给手机。#include SoftwareSerial.h #include DHT.h #define DHTPIN 2 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); SoftwareSerial bleSerial(10, 11); // RX, TX (连接BLE模块的TX, RX) void setup() { Serial.begin(9600); // 用于调试的串口 bleSerial.begin(9600); // 与BLE模块通信的软串口 dht.begin(); // 等待BLE模块启动 delay(2000); // 切换到命令模式假设物理开关已在CMD或使用 // 但我们通过软串口发送物理开关拨到UART我们用切换 bleSerial.print(\r\n); delay(100); // 等待切换 bleSerial.readString(); // 清空缓冲区可能的OK // 配置BLE模块 configureBLE(); // 切换回数据模式 bleSerial.print(\r\n); delay(100); } void loop() { float h dht.readHumidity(); float t dht.readTemperature(); if (isnan(h) || isnan(t)) { Serial.println(读取DHT22失败); return; } // 构建JSON格式的数据字符串 String data {\temp\: String(t) ,\humi\: String(h) }; // 在数据模式下直接发送字符串BLE模块会通过蓝牙UART发送出去 bleSerial.println(data); Serial.print(已发送: ); Serial.println(data); delay(5000); // 每5秒发送一次 } void configureBLE() { sendCommand(ATE0); // 关闭回显 sendCommand(ATGAPDEVNAMEEnvMonitor); // 设置设备名 sendCommand(ATGAPINTERVALS320,80,160,0,500); // 设置广播与连接间隔 sendCommand(ATBLEPOWERLEVEL4); // 设置发射功率为4dBm最大 sendCommand(ATGAPSTARTADV); // 开始广播 } bool sendCommand(const char* cmd) { bleSerial.println(cmd); delay(50); // 等待响应 String response bleSerial.readStringUntil(\n); if (response.indexOf(OK) ! -1) { return true; } else { Serial.print(命令失败: ); Serial.println(cmd); Serial.print(响应: ); Serial.println(response); return false; } }5.3 手机端数据接收与处理在手机端你可以使用任何支持BLE UART服务的App例如nRF UART最简单直接显示收到的字符串。Adafruit Bluefruit LE Connect功能更强大内置控制面板、UART控制台、DFU升级等。自己开发App使用iOS的CoreBluetooth或Android的BluetoothLeScanner API连接到设备的UART服务UUID: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E并订阅RX特征的通知。当手机App连接上“EnvMonitor”设备后每隔5秒就会收到一条如{temp:25.6,humi:60.2}的JSON字符串你可以轻松地将其解析并显示在界面上。5.4 项目优化与注意事项功耗优化本项目每5秒发送一次数据连接间隔为50-100ms功耗相对较高。如果使用电池供电可以增加数据发送间隔如30秒。延长连接间隔如ATGAPINTERVALS320,400,800,0,500。在无数据发送时让单片机进入休眠模式通过BLE模块的中断唤醒引脚来唤醒。数据可靠性在UART透传模式下如果蓝牙连接不稳定数据可能会丢失。对于关键数据可以在应用层设计简单的应答机制。例如手机收到数据后通过BLE UART回发一个“ACK”单片机收到“ACK”后才发送下一条数据。缓冲区管理BLE单次数据传输有MTU限制通常20-23字节。虽然模块有内部FIFO但如果单片机持续高速发送数据仍可能溢出。确保发送速率低于蓝牙链路的平均吞吐量在稳定的连接下9600波特率是安全的。通过这个完整的项目你应该能够掌握使用Adafruit Bluefruit LE Friend模块进行BLE产品原型开发的全流程。从硬件连接到AT命令配置再到数据收发和手机端交互这套方案极大地简化了无线功能的实现让你可以更专注于产品本身逻辑的开发。
BLE串口透传模块实战:从AT命令到环境监测器开发
1. 项目概述从串口到蓝牙的桥梁如果你手头有一个单片机项目需要把传感器数据无线发送到手机或者想用手机App控制一个小设备蓝牙低功耗BLE几乎是绕不开的技术。但一提到BLE开发很多人第一反应是头大——要啃蓝牙协议栈、理解GATT、编写复杂的配对和连接代码光是环境搭建就能劝退不少人。我自己在几年前做第一个可穿戴设备原型时就深有体会。当时为了把心率数据从STM32发到手机折腾了整整两周的蓝牙协议。直到后来遇到了像Adafruit Bluefruit LE Friend这样的模块才意识到原来BLE开发可以如此“偷懒”。这个模块的核心思想非常巧妙它把复杂的BLE协议栈和射频部分全部封装在一块小小的板子上对外只暴露一个最古老、最通用的接口——串口UART。你不需要懂任何蓝牙GATT服务的细节只需要像操作传统的串口Wi-Fi模块一样通过发送AT命令字符串就能完成蓝牙广播、连接、数据收发等一系列操作。简单来说Bluefruit LE Friend就是一个“蓝牙转串口”的透明桥。在数据模式下你从单片机串口TX引脚发送的任何字节都会原封不动地通过蓝牙无线传输到已连接的手机App例如Nordic的nRF UART反之手机App发送的数据也会从模块的RX引脚输出让你的单片机轻松接收。而在命令模式下你可以通过一套扩展的AT指令集精细地控制模块的几乎所有行为比如修改设备名称、调整广播参数、模拟键盘鼠标HID设备甚至创建自定义的GATT服务。这种设计将开发难度从“射频协议工程师”级别降到了“会用串口发送字符串”的级别非常适合创客、嵌入式爱好者以及需要快速验证产品原型的硬件工程师。本指南将基于我多年使用此类模块的经验不仅带你走通从开箱到双向通信的完整流程更会深入拆解AT命令背后的工作原理、分享实际项目中积累的配置技巧和避坑心得。无论你是想做一个通过手机遥控的智能小车还是将温湿度数据上传到手机的监测器这篇文章都能为你提供一套即拿即用的解决方案。2. 硬件解析与初始配置2.1 模块版本识别与核心硬件布局Adafruit Bluefruit LE Friend 主要有三个硬件版本选对版本关系到你能使用的功能和固件。我手头经典型号是v2.0黑色PCB版它采用FTDI FT231X作为USB转串口芯片板载一个标准的10针SWD调试接口方便高级用户刷写自定义固件。而目前市面上主流的是v3.0版为了成本优化将USB桥接芯片换成了CP2104并移除了SWD接口。对于绝大多数仅使用AT命令进行应用开发的用户来说v3.0完全够用且更便宜。最老的v1.0蓝色PCB版内存较小已不推荐使用。拿到模块后首先认识板上的几个关键部件这对后续调试至关重要模式选择开关位于USB口附近拨向“CMD”进入命令模式拨向“UART”进入数据模式。这是整个模块功能切换的物理开关。TXD/RXD状态LED两个小灯分别对应串口数据的发送和接收。当你通过USB向模块发送数据时TXD灯会闪烁模块收到来自蓝牙的数据时RXD灯会闪烁。这是判断数据流是否正常的最直观依据。DFU模式按钮按住此按钮再插入USB模块会进入固件升级模式此时可以通过手机App进行无线固件更新。模式指示灯LED用于指示当前工作模式。快速闪烁两次停顿三秒循环往复表示处于数据模式快速闪烁三次停顿三秒则表示处于命令模式。如果LED以恒定频率快速闪烁则说明进入了DFU模式。连接状态LED当模块与手机等中心设备成功建立蓝牙连接后此蓝色LED会常亮。断开连接则会熄灭。这是判断连接状态的最重要标志。实操心得很多新手第一次使用时会忽略模式指示灯。务必牢记“闪2下是UART闪3下是CMD”。如果发现发送AT命令没反应第一件事就是检查这个灯的闪烁模式大概率是开关拨错了位置。2.2 驱动安装与串口终端配置模块需要通过USB与电脑通信因此第一步是安装正确的USB转串口驱动。对于v3.0 (CP2104芯片)你需要安装Silicon Labs的CP210x USB转UART桥接器驱动。去Silicon Labs官网下载最新的VCP驱动程序即可。对于v1.0/v2.0 (FTDI芯片)你需要安装FTDI的FT231X驱动。可以从FTDI官网下载。安装完成后将模块插入电脑USB口在设备管理器中应该能看到一个新的COM端口Windows或/dev/tty.usbserial-*设备macOS/Linux。接下来需要一个串口终端软件。我个人的选择是WindowsTera Term。免费、开源、功能强大。macOS/LinuxCoolTerm或直接使用命令行工具如screen、minicom。无论使用哪种软件串口参数必须严格设置如下波特率9600数据位8停止位1校验位无流控制硬件流控 (RTS/CTS)必须启用注意事项“硬件流控”是很多新手会栽跟头的地方。BLE模块内部缓冲区很小如果电脑发送数据过快而蓝牙链路传输较慢数据就会丢失。启用硬件流控后模块可以通过RTS/CTS信号线告诉电脑“暂停发送”从而避免数据溢出。在Tera Term中需要在“设置 串口端口”中勾选“RTS/CTS”在CoolTerm中需要在“Options Flow Control”中选择“Hardware”。配置完成后打开串口连接。先将模式开关拨到“CMD”观察模式指示灯是否为“三闪一停”。然后在终端里输入AT并回车如果模块回复OK恭喜你通信链路已经建立。3. AT命令集深度解析与应用AT命令是控制模块的灵魂。Adafruit为其BLE模块设计了一套丰富且逻辑清晰的命令集远超简单的“蓝牙串口”范畴。理解其语法和分类能让你真正释放模块的潜力。3.1 AT命令语法与四种操作模式Bluefruit LE的AT命令遵循经典的Hayes命令集风格但更加规整。每条命令都有四种可能的操作模式通过后缀来区分测试命令 (?)用于查询某个命令是否存在或获取其参数格式。例如ATBLEPOWERLEVEL?会返回OK表示该命令可用如果命令不存在则返回ERROR。在编写自动配置脚本时先用测试命令探路是个好习惯。写命令 (参数)用于设置参数。这是最常用的模式。例如设置发射功率为-8dBmATBLEPOWERLEVEL-8。如果参数合法返回OK非法则返回ERROR。执行命令 (无后缀)用于触发一个动作该动作不需要或已预设参数。例如执行系统复位ATZ或进入DFU模式ATDFU。读命令 (?)用于读取当前配置或状态。例如读取当前发射功率ATBLEPOWERLEVEL?会返回类似-4\r\nOK的结果。核心原理这种设计将“查询”、“设置”、“执行”清晰地分离开使得命令集非常易于被机器解析也便于开发者编写稳定的控制程序。你几乎可以像操作一个字典或键值对数据库一样操作这个模块。3.2 基础与硬件控制命令实战让我们从最基础的命令开始这些命令是你与模块交互的基石。ATI(识别信息)这是你的“健康检查”第一命令。输入ATI你会得到类似下面的信息BLEFRIEND nRF51822 QFAAG00 FB462DF92A2C8656 0.7.7 0.7.7 Feb 24 2015 S110 8.0.0, 0.0 OK这七行信息依次是板卡名称、蓝牙SoC型号、唯一序列号、核心库版本、固件版本、编译日期、SoftDevice版本和Bootloader版本。每次拿到新模块先用ATI确认固件版本因为不同版本支持的命令可能有差异。ATE(回显控制)ATE1开启本地回显你输入的字符会在终端显示两次一次是你打的一次是模块回的。ATE0则关闭回显。在编写单片机程序自动发送AT命令时务必关闭回显(ATE0)否则你会收到额外的字符干扰解析。(动态模式切换)这是一个非常实用的技巧。你不需要每次都去拨动物理开关。在数据模式下发送\r\n注意要有回车换行模块会切换回命令模式并回复OK。再次发送\r\n则切回数据模式。你可以用ATMODESWITCHEN命令来配置是否允许从蓝牙侧手机也通过切换模式默认是禁止的以防手机App误操作。硬件访问命令模块暴露了部分MCU的硬件功能这在调试时非常有用。ATHWGPIO可以读取或设置GPIO引脚电平。例如ATHWGPIO14,1设置引脚14为高电平。但要注意很多引脚已被模块内部功能占用如LED、按钮乱设可能导致异常。使用前最好查阅原理图。ATHWADC读取指定ADC通道的值。例如ATHWADC0读取通道0的ADC值0-255或0-1023取决于ADC分辨率配置。ATBAUDRATE谨慎使用可以修改串口波特率。虽然支持最高1Mbps但nRF51的UART性能有限在高速率下极易丢包。对于稳定的BLE UART透传强烈建议保持默认的9600波特率。如果你确实需要更改记住修改后终端软件的波特率设置也要同步更改。3.3 BLE核心功能配置GAP与连接管理GAP通用访问配置文件负责设备的广播、扫描和连接。这部分命令决定了你的设备如何被外界发现和连接。ATGAPDEVNAME(设置设备名称)这是手机扫描时看到的名称。ATGAPDEVNAMEMySensor即可修改。名称不宜过长建议在10个字符以内。ATGAPINTERVALS(设置广播参数)这个命令直接影响功耗和连接速度。格式为ATGAPINTERVALS广播间隔,最小连接间隔,最大连接间隔,从设备延迟,连接超时。广播间隔单位0.625ms。设得太短如ATGAPINTERVALS32,40,40,0,500广播间隔20ms功耗高但手机能更快发现设得太长如ATGAPINTERVALS1600,40,40,0,500间隔1秒省电但手机可能需要多等一会儿才能扫到。平衡点通常在100-500ms之间。连接间隔连接建立后主从设备通信的时间间隔。间隔越小如7.5ms实时性越高但功耗也越大间隔越大如1s越省电但数据延迟明显。ATGAPINTERVALS,,80,160,表示连接间隔在50ms到100ms之间手机中央设备会在这个范围内协商一个具体值。ATGAPSTARTADV/ATGAPSTOPADV(启停广播)ATGAPSTARTADV开始广播模块可被扫描到ATGAPSTOPADV停止广播进入低功耗状态如果未连接。一个常见误区停止广播并不会断开现有连接已连接的设备依然可以通信。要断开连接需要使用ATGAPDISCONNECT。ATBLEGETPEERADDR/ATBLEGETRSSI在连接建立后可以分别用于获取已连接对端设备的蓝牙MAC地址和接收信号强度指示。RSSI值对于粗略估算距离或信号质量很有帮助。3.4 数据通道的基石BLE UART服务模块内置了一个最重要的服务UART服务。这就是实现“蓝牙串口透传”功能的核心。服务原理模块在GATT服务器中创建了一个UART服务包含两个特征值TX特征 (UUID: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E)属性为Write或Write Without Response。手机向这个特征写入数据模块通过串口RX引脚输出。RX特征 (UUID: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E)属性为Notify。当模块从串口TX引脚收到数据时会通过这个特征以通知的方式发送给手机。 这是一种非常高效的设计利用了BLE的“通知”机制手机无需轮询模块有数据就推送给手机。相关AT命令ATBLEUARTFIFO查询UART FIFO先入先出缓冲区中当前积压的字节数。在调试数据吞吐量时有用。ATBLEUARTTX和ATBLEUARTRX这两个命令主要用于调试。在命令模式下你可以用ATBLEUARTTXHello模拟从串口收到“Hello”数据并检查手机端是否能收到通知反之ATBLEUARTRX可以读取从手机发来但尚未被取走的数据在数据模式下这些数据会直接输出到串口。与手机App通信实战将模式开关拨到UART模式灯闪2下。打开手机上的nRF Connect或nRF UARTApp。扫描并连接名为“UART”的设备。连接成功后模块的连接状态LED常亮。在手机App的UART界面发送“Hello”你会在电脑的串口终端上看到“Hello”。在电脑的串口终端里输入“World”手机App上会立刻显示“World”。这个过程完美演示了双向透传。对于你的单片机项目只需将单片机的串口TX、RX、GND与模块对应引脚连接单片机代码就完全像在与另一个串口设备通信无需任何蓝牙代码。4. 高级功能与自定义服务开发4.1 模拟HID设备键盘与鼠标这是Bluefruit LE Friend一个非常有趣且实用的功能。你可以让它模拟成一个蓝牙键盘或鼠标直接控制电脑或手机。这在制作自定义遥控器、演示器或无障碍设备时特别有用。启用HID首先需要启用HID服务。ATBLEHIDEN1开启HID总开关。ATBLEKEYBOARDEN1单独启用键盘功能ATBLEHIDMOUSEEN1启用鼠标功能。发送按键单个按键ATBLEKEYBOARDchar例如ATBLEKEYBOARDA发送字母A。组合键需要用到修饰键值和键盘扫描码。例如发送CtrlCATBLEKEYBOARDCODE02,00,00,00,00,00,06,00,00,00,00,00,00,00,00,00这个16字节的数组里第一个字节02代表左Ctrl键按下第六个字节06代表字母C的HID使用页扫描码。释放按键需要发送全零的数组。实际操作中我强烈建议不要手动拼写这个数组而是利用Adafruit提供的Arduino或Python库来生成它们有友好的封装函数。控制鼠标ATBLEHIDMOUSEMOVEx,y,wheel移动鼠标指针。x, y为相对移动量-127 到 127wheel为滚轮移动量。ATBLEHIDMOUSEBUTTONbuttons控制鼠标按键。buttons是一个位掩码1左键2右键4中键。 例如ATBLEHIDMOUSEMOVE10,0,0让指针右移10个单位ATBLEHIDMOUSEBUTTON1点击左键。避坑指南模拟HID设备时连接间隔对体验影响巨大。如果连接间隔设得太大如500ms鼠标移动会感到明显的卡顿。建议将连接间隔设置为最小值如7.5ms以获得流畅体验但这会显著增加功耗。4.2 创建自定义GATT服务与特征值虽然内置的UART和HID服务覆盖了大部分应用但有时你需要传输特定结构的数据如传感器三轴数据或者需要符合某个标准的蓝牙设备配置文件。这时就需要创建自定义GATT服务。模块提供了ATGATTADDCHAR和ATGATTCHAR等命令来动态构建服务。但请注意在Bluefruit LE Friend上自定义GATT服务是存储在RAM中的断电即丢失。每次上电都需要重新配置。这对于固定功能的产品原型来说可能不够方便但对于动态配置和测试来说足够了。创建一个简单的心率测量服务示例清除现有服务ATGATTCLEAR添加心率服务心率服务的标准UUID是0x180D。ATGATTADDSERVICE0x180D添加心率测量特征该特征UUID为0x2A37属性为Notify服务器主动通知客户端。ATGATTADDCHAR0x2A37,0x100x10代表Notify属性添加身体传感器位置特征UUID为0x2A38属性为Read。ATGATTADDCHAR0x2A38,0x020x02代表Read属性设置身体传感器位置值假设是手腕佩戴值为3。ATGATTCHAR2,3假设这是添加的第二个特征索引从1开始开始广播ATGAPSTARTADV现在用手机上的nRF ConnectApp扫描并连接你的设备就能在服务列表中看到标准的“Heart Rate”服务并能读取传感器位置以及订阅心率测量通知。你可以通过ATGATTCHAR1,value假设心率测量是第一个特征来模拟发送一个心率值例如0x40代表64 BPM手机App会立刻收到通知。这个过程虽然需要手动输入多条AT命令但它清晰地揭示了BLE设备是如何通过GATT组织数据的。对于量产产品这些配置通常会编译进固件一劳永逸。4.3 Beacon功能与空中升级iBeacon/Eddystone模拟模块可以配置为广播iBeacon或Eddystone格式的帧变成一个蓝牙信标。这对于室内定位或信息推送应用很有用。命令如ATBLEBEACON可以设置UUID、Major、Minor值和发射功率校准值。设置后模块会持续广播信标帧任何支持信标扫描的App如手机上的“蓝牙扫描器”都能接收到。空中升级这是Adafruit模块的一大亮点。当有新固件发布时你无需任何硬件编程器。让模块进入DFU模式按住DFU按钮插入USB或发送ATDFU命令。模式指示灯会变成快速恒定的闪烁。在手机上安装Adafruit Bluefruit LE ConnectApp。打开App它会自动搜索处于DFU模式的设备。选择设备App会从Adafruit服务器获取可用的固件列表选择并开始升级。 整个过程无线完成非常方便。升级前务必确保设备电量充足升级过程中不要断开蓝牙连接。5. 实战项目构建一个智能环境监测器让我们综合运用以上知识构建一个实际项目一个通过BLE将温湿度数据发送到手机的环境监测器。5.1 系统架构与硬件连接核心控制器我们使用一块常见的开发板如Arduino Uno或ESP32。这里以Arduino为例。传感器DHT22温湿度传感器。BLE模块Adafruit Bluefruit LE Friend。连接方式Arduino 5V - BLE Friend VINArduino GND - BLE Friend GNDArduino TX (Pin 1) - BLE Friend RXArduino RX (Pin 0) - BLE Friend TXDHT22 Data Pin - Arduino Digital Pin 2重要提示Arduino Uno的Pin 0和1也是串口监视器的端口。当BLE模块连接后会占用此硬件串口导致你无法通过USB打印调试信息。在最终部署时这没问题但在开发调试阶段建议使用SoftwareSerial库将BLE模块连接到其他数字引脚如Pin 10为RXPin 11为TX以便保留主串口用于调试输出。5.2 Arduino端代码逻辑与AT命令发送Arduino代码的核心是初始化串口、配置BLE模块、读取传感器数据并通过串口将数据发送给BLE模块模块在UART模式下会自动转发给手机。#include SoftwareSerial.h #include DHT.h #define DHTPIN 2 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); SoftwareSerial bleSerial(10, 11); // RX, TX (连接BLE模块的TX, RX) void setup() { Serial.begin(9600); // 用于调试的串口 bleSerial.begin(9600); // 与BLE模块通信的软串口 dht.begin(); // 等待BLE模块启动 delay(2000); // 切换到命令模式假设物理开关已在CMD或使用 // 但我们通过软串口发送物理开关拨到UART我们用切换 bleSerial.print(\r\n); delay(100); // 等待切换 bleSerial.readString(); // 清空缓冲区可能的OK // 配置BLE模块 configureBLE(); // 切换回数据模式 bleSerial.print(\r\n); delay(100); } void loop() { float h dht.readHumidity(); float t dht.readTemperature(); if (isnan(h) || isnan(t)) { Serial.println(读取DHT22失败); return; } // 构建JSON格式的数据字符串 String data {\temp\: String(t) ,\humi\: String(h) }; // 在数据模式下直接发送字符串BLE模块会通过蓝牙UART发送出去 bleSerial.println(data); Serial.print(已发送: ); Serial.println(data); delay(5000); // 每5秒发送一次 } void configureBLE() { sendCommand(ATE0); // 关闭回显 sendCommand(ATGAPDEVNAMEEnvMonitor); // 设置设备名 sendCommand(ATGAPINTERVALS320,80,160,0,500); // 设置广播与连接间隔 sendCommand(ATBLEPOWERLEVEL4); // 设置发射功率为4dBm最大 sendCommand(ATGAPSTARTADV); // 开始广播 } bool sendCommand(const char* cmd) { bleSerial.println(cmd); delay(50); // 等待响应 String response bleSerial.readStringUntil(\n); if (response.indexOf(OK) ! -1) { return true; } else { Serial.print(命令失败: ); Serial.println(cmd); Serial.print(响应: ); Serial.println(response); return false; } }5.3 手机端数据接收与处理在手机端你可以使用任何支持BLE UART服务的App例如nRF UART最简单直接显示收到的字符串。Adafruit Bluefruit LE Connect功能更强大内置控制面板、UART控制台、DFU升级等。自己开发App使用iOS的CoreBluetooth或Android的BluetoothLeScanner API连接到设备的UART服务UUID: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E并订阅RX特征的通知。当手机App连接上“EnvMonitor”设备后每隔5秒就会收到一条如{temp:25.6,humi:60.2}的JSON字符串你可以轻松地将其解析并显示在界面上。5.4 项目优化与注意事项功耗优化本项目每5秒发送一次数据连接间隔为50-100ms功耗相对较高。如果使用电池供电可以增加数据发送间隔如30秒。延长连接间隔如ATGAPINTERVALS320,400,800,0,500。在无数据发送时让单片机进入休眠模式通过BLE模块的中断唤醒引脚来唤醒。数据可靠性在UART透传模式下如果蓝牙连接不稳定数据可能会丢失。对于关键数据可以在应用层设计简单的应答机制。例如手机收到数据后通过BLE UART回发一个“ACK”单片机收到“ACK”后才发送下一条数据。缓冲区管理BLE单次数据传输有MTU限制通常20-23字节。虽然模块有内部FIFO但如果单片机持续高速发送数据仍可能溢出。确保发送速率低于蓝牙链路的平均吞吐量在稳定的连接下9600波特率是安全的。通过这个完整的项目你应该能够掌握使用Adafruit Bluefruit LE Friend模块进行BLE产品原型开发的全流程。从硬件连接到AT命令配置再到数据收发和手机端交互这套方案极大地简化了无线功能的实现让你可以更专注于产品本身逻辑的开发。