串口设备如何通过BLE实现手机实时数据接收:从协议设计到调试实践
2026/9/15 10:52:40 网站建设 项目流程

1. 数传方案选型:为什么 BLE 成了这类项目的默认选择

做嵌入式设备的数据传输,说来说去绕不开三种无线方案:Wi-Fi、4G/5G、BLE。前几年大家一窝蜂去搞 Wi-Fi 模组,本地网络环境好、带宽大、速度痛快,但功耗和成本也上来了。做便携式设备的人很快发现,一块 18650 电池给 Wi-Fi 模组供电,还没等数据传完,电池先报警了。4G 更不用多说,资费、入网、天线、SIM 卡这些事情,对很多中小项目来说都是负担。相比之下 BLE 这个方案,协议栈成熟、模组价格低、功耗极低、手机原生支持,简直是“串口到手机”这条路最自然的接法。

我第一次做类似的项目,是在一个便携式数据采集器上。设备端是一个 STM32F103 系列 MCU,通过 UART 接收各个传感器的数据,要把它实时同步到手机 App 上。当时选型的时候对比过 ESP8266、CC2541、nRF52832 这些方案,最终选了 BLE 模组,原因很简单:设备大多数时间处于低频数据输出状态,每秒只有几十字节,BLE 的 2.4GHz 频段、20 字节到 244 字节的 payload 完全够用。更关键的是,BLE 协议栈里专门有一套适用于低功耗设备的 GATT 数据交互机制,配合 notify 通知特性,服务器端主动推数据给客户端,不需要客户端一次次轮询,这正好匹配了“串口收什么,手机就看什么”的需求。

所以这篇博客里,我会把从串口数据采集、BLE 模组转发、到手机 App 接收解析的完整链路拆开讲一遍。适合正在做 IoT 外设、运动健康设备、工业传感器数据采集,或者纯粹想把一个串口设备通过 BLE 变成可用手机操作的项目的人。你不需要是蓝牙协议专家,也不用啃完 3000 页的蓝牙核心规范,我会沿着实际代码和调试过程来写,让你能直接上手把这条路跑通。

1.1 三种无线数传方案的实际对比

先说结论:选 BLE 不是因为 BLE 能通吃所有场景,而是在“串口设备与手机之间传小数据”这个具体场景下,它的综合成本最低。Wi-Fi 方案的优点是带宽大、协议标准、跟路由器基础设施天然对接,适合固件升级、视频流、批量文件同步这类数据量大的任务。缺点在硬件成本和功耗上,一个 Wi-Fi 模组加天线匹配电路、电源管理,实际 BOM 成本和调试成本都要比 BLE 模组高不少。在电池供电的产品中,Wi-Fi 模组平均电流动辄几十到上百毫安,这对工作电流只有几十到几百微安量级的 BLE 模组来说,差距是数量级的。

4G/5G 的能力最强,能实现真正的互联网远程连接,设备在任何有信号的地方都可以回传数据。但代价也最重,模块贵、SIM 卡需要管理、流量费需要长期投入、天线设计和入网认证还牵扯到很多合规问题。如果是做公网远程监控、车联网、物流追踪这类必须跨地域的项目,4G 值得上;如果只是手机在旁边看一下设备状态,用 4G 就是杀鸡用牛刀,还得每个月养着流量卡,纯属自找麻烦。

BLE 在短距无线通信里还有一个隐性优势:手机原生支持。iOS 从 iPhone 4s 开始就内置了 CoreBluetooth 框架,Android 从 4.3 开始提供 BLE API。这意味着你不需要用户在手机上装额外的硬件接收器,也不需要 App 去访问什么设备管理器,打开蓝牙、扫一扫、连上就完事。对用户来说,这种“手机直接连设备”的交互成本几乎为零。

1.2 BLE 带来的开发门槛和回报

BLE 的短板也是真实存在的。第一,速率低,实际有效吞吐量取决于连接间隔和 MTU 大小,常见情况下能做到几十 KB/s 就算不错了,不适合大批量传输。第二,距离有限,BLE 的典型有效距离在户外空旷环境下只有几十米,室内穿墙后衰减严重。第三,虽然协议栈帮你做了很多工作,但理解和调优连接参数、MTU、notify 行为,还是需要花时间去吃透。

不过回到我们这个“串口到手机”的场景,BLE 的这些短板恰好都不算问题。串口设备本身数据量通常不大,传感器数据、状态帧、控制指令,一帧撑死几十字节。距离方面,人要操作设备,设备基本就在手边。开发难度方面,BLE 协议虽然复杂,但模组厂商已经把底层的链路层、L2CAP、ATT/GATT 都封好了,你面对的是 UART 接口和 AT 指令或简单的 SDK 接口。实际上,你真正要设计的核心协议只有一层:应用层如何把串口数据变成 GATT 上面的值。

2. 串口侧:数据通路的起点和最容易翻车的地方

很多人做这类项目会把注意力全放在 BLE 上,结果问题全出在串口。串口看起来简单,无非 TX、RX、GND 三根线,但在实际项目中,波特率不匹配、电平不匹配、硬件流控忘关、数据帧粘连,这些问题都会让你在 BLE 端排查到怀疑人生。因为一旦串口这里的数据就是错的、丢的、乱的,蓝牙链路再稳定也白搭。

2.1 串口参数配置:不止是 9600 和 115200

串口通信的参数其实是一组组合:波特率、数据位、停止位、校验位、流控。绝大多数人用 8N1(8 个数据位、无校验、1 个停止位),这没问题。问题出在波特率的选择上,很多传感器模块默认出厂是 9600,也有一批是 115200,还有小众模块用 57600、38400,甚至有翻遍整个数据手册都找不到标注的。我的建议是,在项目启动阶段就把波特率统一约定成一个固定值,并且把它写进双方通信协议里,最好通过配置通道进行握手确认。

波特率和 BLE 数传之间的关系很容易被忽略。串口侧如果以 115200 波特率持续向 BLE 模组灌数据,而 BLE 侧的实际传输吞吐量只有 30 KB/s 左右,数据就会在模组的缓冲区里堆积。BLE 模组的 UART 缓冲区一般只有几百字节到几 KB,堆满了就丢帧。所以串口侧必须做发送节奏控制,要么降低波特率,要么增加流控/应答机制,要么在应用层做帧间隔控制。

一个可行的做法是:串口侧不把数据一股脑全发出去,而是先按“一帧”为单位打包,帧与帧之间留出 10 ms 到 50 ms 的空隙,给 BLE 协议栈留足时间把数据推送到手机端。这样虽然降低了串口的瞬时吞吐量,但保证了整条链路的可靠性。数据链路的吞吐量瓶颈在 BLE 侧,串口这边再快也只是把数据往缓冲区里堆而已。

2.2 设备侧数据协议设计:不要上来就裸传

串口数据如果只是单字节、单通道的传感器值,裸传问题不大。但实际项目中,一个设备上往往有很多种数据:温度、湿度、设备状态、累计量、告警事件,甚至还有配置项和升级包。这些数据混在一起走同一个串口,如果没有协议封装,接收端根本没法区分哪段是什么。

我建议在设备端就设计一套最简帧格式:

字段长度说明
帧头2 字节固定值 0xAA 0x55,用于同步
长度1 字节从类型到校验前所有字节数
类型1 字节0x01 传感器数据,0x02 状态帧,0x03 配置帧
数据N 字节实际负载
校验1 字节所有字节异或或 CRC8

这个格式看起来朴素,但足够解决“数据从哪开始、到哪结束、是什么类型、对不对”这几个核心问题。在实际调试时,串口助手和手机 App 都靠这个格式来正确切割数据流。

2.3 串口到 BLE 模块:电平匹配与接线避坑

串口电平不匹配是新手第二容易踩的坑。STM32 的 UART 引脚一般是 3.3V TTL 电平,树莓派的 UART 也是 3.3V,但老的 Arduino 或者 5V 单片机可能是 5V TTL 电平。如果直接把 5V 设备接到 3.3V 的 BLE 模组串口上,轻则数据乱码,重则烧坏模组。连接之前一定要确认双方的电平范围。如果不匹配,用双向电平转换模块,几块钱一个,不贵。

接线顺序也有讲究。调试初期,很多人会忘记共地,串口通信明明接好了 TX/RX,但数据就是乱码。原因很简单:UART 是异步串行通信,双方的参考地必须一致。如果没有共地,信号电平的参考点是浮动的,收到的数据自然全是噪声。模块间接线务必保证 GND 相连,这一点请刻在脑子里。

硬件流控(RTS/CTS)默认关闭,如果打开了,但另一侧没有对应引脚连接,会导致发送方等流控信号等到天荒地老,数据卡死。调试时如果发现发了几帧就停了,先检查是不是把流控给开了。

3. BLE 通信链路:广播、连接与 GATT 服务设计

串口侧的数据准备好了,接下来就是 BLE 模组的活。这里要理解 BLE 的通信模型:外设(Peripheral)在广播自己的存在,中心设备(Central,比如手机)扫描到广播后发起连接。连接建立之后,双方通过 GATT(Generic Attribute Profile)进行数据交互。GATT 的结构是 Service(服务)- Characteristic(特征)- Value(值)三层。你要把串口数据变成手机能读到的值,就得在这三层上做文章。

3.1 广播数据怎么配,才能让 App 快速找到设备

广播数据是设备的第一张名片,手机 App 扫描设备时,主要靠广播包里携带的信息来识别目标设备。广播包可以包含设备名称、Service UUID、厂商自定义数据等。如果广播数据里没有任何可过滤的信息,App 只能把所有扫描到的设备都列出来,体验非常差。

实际经验是,在广播包里把自定义 Service UUID 带上,App 端扫描时按这个 UUID 过滤。这样即使两台设备名字一样,也能通过 UUID 区分。广播名不要设置太长,BLE 广播包本身大小有限制(传统广播通道包最大 31 字节),设备名加 Service UUID 加厂商数据很容易超。如果超了,很多协议栈会自动把部分数据截掉或放不进广播包,导致手机端扫描信息不全。

这里还有个细节:广播类型选择。可连接非定向广播(Connectable Undirected Advertising)是默认的选择,适合大多数外设。如果设备已经跟手机建立了连接,还想让其他手机也能扫描到它,就得改广播策略,但这属于高级玩法,要根据具体模组 SDK 来配置,这里不做展开。

3.2 连接参数:连接间隔、从机延迟与超时

连接建立之后,BLE 链路的效率由连接参数决定。核心参数有三个:连接间隔(Connection Interval)、从机延迟(Slave Latency)、超时时间(Supervision Timeout)。

连接间隔是主机和从机之间两次通信的时间间隔,范围从 7.5ms 到 4s。间隔越短,数据交互越及时,但功耗越高。间隔越长,功耗越低,但数据延迟越大。从机延迟允许从机跳过若干次连接事件而不必每次都被主机唤醒,进一步省电。超时时间是链路认为连接已经丢失的时间阈值。

对“串口数据实时推送手机”这个场景,我推荐的参数组合是:连接间隔 30ms 到 50ms,从机延迟 0 到 4,超时时间 5 秒以上。如果数据频率很高,比如每 20ms 就要推一帧,连接间隔就不要超过 20ms,否则数据会在模组里排队,加大延迟和丢包风险。如果设备对功耗敏感,可以把间隔拉大到 100ms,同时把应用层的数据合并成更大的包再发。

需要特别注意的是,Android 手机上的系统蓝牙栈可能会根据自己的策略修改连接参数,你通过 GATT 请求设置的连接参数不一定能生效。实测中,iOS 对连接参数的协商相对严格,Android 各家手机差异很大。遇到参数不一致时,不要死磕连接参数,而是在应用层加缓冲和重发机制。

3.3 GATT 服务设计:一个服务搞定还是多服务拆分

GATT 服务设计直接决定了 App 端解析逻辑的复杂度。最省事的方式是建一个自定义 Service,里面放两个 Characteristic:一个用于写入(手机给设备发数据),一个用于通知(设备给手机发数据)。核心代码如下:

  • Write Characteristic:属性为 Write / Write Without Response,负责接收 App 下发的控制指令、配置参数。
  • Notify Characteristic:属性为 Notify,负责主动推送设备发出的串口数据。必须同时支持 CCCD(Client Characteristic Configuration Descriptor),因为手机端需要先写入 0x01 来订阅通知,才能收到 Notify 数据,这个步骤很多人会忘。

不要第二个服务,也不必把每种数据类型拆成单独的 Characteristic。原因很简单:BLE 的读写操作一次能承载的数据有限,拆分太细反而提高了 App 端逻辑的复杂度。我更倾向于在 Notify Characteristic 上用应用层协议区分数据类型,也就是说,GATT 层面的设计保持最小化,数据语义交给上层的帧格式去解释。这样做还有一个好处:如果设备以后新增数据类型,不需要改 GATT 结构,只需要在协议里加类型值。

4. 手机 App 端:从扫描到收数的完整逻辑

手机 App 是整条链路的终点,也是用户直接面对的部分。App 端的核心任务有三个:扫描到目标设备、建立 GATT 连接、订阅 Notify 并持续接收数据。Android 和 iOS 的实现思路不同,但逻辑相通。

4.1 Android 端扫描与连接

Android 端的 BLE 开发在过去几年变化很大,API 从传统的 startLeScan 迁移到了 BluetoothLeScanner,运行时权限也增加了定位权限要求。很多老教程还在用已经废弃的 API,照着做编译报错是小事,关键是在 Android 12 以上机型上根本扫不到设备。

现代 Android 扫码的基本步骤如下:

  1. 在 AndroidManifest.xml 中声明 BLUETOOTH_SCAN、BLUETOOTH_CONNECT 权限,Android 12 以上需要动态申请。
  2. 获取 BluetoothLeScanner 实例。
  3. 构建 ScanFilter,按 Service UUID 过滤目标设备。
  4. 启动扫描,回调中拿到 ScanResult,通过设备名称或地址连接。

连接时要用BluetoothGattCallback来处理各种回调。在onConnectionStateChange中判断连接成功,然后立即调用discoverServices()去发现服务。服务发现完成之后再通过getService()拿到你的自定义 Service,然后用setCharacteristicNotification()去订阅 Notify。

4.2 notify 通道:数据从设备到手机的关键

订阅 Notify 的过程有个经典坑:只调用setCharacteristicNotification()是不够的。你还需要往对应 Characteristic 的 CCCD(0x2902)描述符写入 0x0100,这才能真正开启通知。很多新手在这步漏掉,结果设备发了半天数据,App 端一个回调都没有。我建议在主流程中加入onDescriptorWrite回调,确认写入成功后再提示用户“已连接”。

数据到达后,onCharacteristicChanged回调会返回整个特征值。如果设备侧数据量较大,而且 MTU 协商后仍然不够,模组和 App 之间往往会在 GATT 层自动进行分包,但手机端 callback 拿到的值可能是分片后的单包。这时候,App 端需要自己负责把收到的这些“半包”按协议拼回完整帧。

Android 设备对 BLE 的兼容性较差的说法并不夸张。不同厂商的蓝牙协议栈对onCharacteristicChanged回调的时机、对包大小的处理、对连接参数的处理都有差异。实测中发现,某些手机在通知频繁时会丢回调,时长不固定。应对办法是:在 App 端做协帧缓存和超时重传机制。具体做法后面讲协议设计时再展开。

4.3 iOS 端与 Android 的差异处理

iOS 端通过 CoreBluetooth 框架实现 BLE,接口设计比 Android 干净不少,但它的行为策略和 Android 有几点不同。第一,iOS 端扫描时也必须通过 Service UUID 过滤,否则会报错,不允许通过设备名来过滤。第二,iOS 对后台 BLE 的支持有严格限制,App 进入后台后仍然可以接收 notify 数据,前提是你预先声明了 UIBackgroundModes 中的bluetooth-centralbluetooth-peripheral,并且用户没有断开连接。第三,iOS 不允许未知设备的 Service 和 Characteristic 被任意读取和写入,必须通过 discoverServices 和 discoverCharacteristics 一步步把 UUID 找出来。

如果项目同时支持 Android 和 iOS,我建议把 BLE 连接流程的核心逻辑统一封装成抽象接口,内部按平台实现。这样平台差异被隔离在底层,上层业务代码只需要关心“收到了什么数据”。不然到了后期,平台逻辑混在一起,排查问题会非常痛苦。

5. 协议设计经验:一帧数据的完整旅程

串口数据到了 BLE 模组,模组通过 GATT 通知发送;App 端收到通知,拿到特征值。看起来是一条简单链路,但实际传输过程中,数据不会像流水一样温顺地按照你定义的帧边界到达。你会发现,有时候一次通知只带了半个帧,有时候一次通知带了 3 个完整帧再加半个帧,更糟的时候,一个帧被拆成 5 个包分好几次通知才到齐。这些问题的根源是“串口的字节流”和“BLE 的分包通知”之间存在粒度不匹配,必须通过应用层协议来解决。

5.1 自定义帧格式:包头、长度、负载、校验

我在前面第 2 节已经给过一种帧格式,这里再把它上升到协议层面说细一点。一个可靠的数据帧至少要满足这几个条件:

  • 接收方可以从随机字节流中准确找到帧的起始位置。
  • 接收方可以确定这一帧到哪里结束。
  • 接收方可以判断这一帧的数据是否在传输过程中损坏。

帧头选固定值 0xAA 0x55,注意如果负载数据里也可能出现 0xAA 0x55,那就要做转义处理,或者靠长度字段来跳过头部。更稳妥的方案是使用带状态机的解析逻辑:从扫描帧头开始,然后读长度,再按长度字段补齐整个帧,最后做校验比对。这种状态机解析方式我在串口助手、BLE App 里都用同一套逻辑,一次封装,到处复用。

校验方式我推荐 CRC8 或者累加和。CRC8 有现成的查表实现,代码量很小,检测能力足够覆盖一帧几十字节的应用层数据。不要用简单的异或,虽然写起来快,但两个字节同时翻转时异或校验检测不出来。如果项目对数据完整性要求高,比如固件升级、关键配置下发,直接上 CRC16 甚至 CRC32。

5.2 MTU 限制下的分包与重组

BLE 默认的 MTU(Maximum Transmission Unit)是 23 字节,其中 ATT 层头部占 3 字节,实际数据载荷只有 20 字节。也就是说,在默认配置下,一个 Notify 最多带 20 字节,如果一帧串口数据有 100 字节,它就要被拆成 5 包发送。Android 和 iOS 都支持通过requestMtu()协商更大的 MTU,Android 一般能到 512 字节,iOS 也有 185 或更大的值,但协商不是万能的,有些旧设备或模组固件不支持。

协商 MTU 后,建议把“单帧数据长度”控制在 MTU 载荷范围内,这样一帧数据可以塞进一次通知里,减少 App 端拼包的工作量。如果一帧确实超过 MTU 载荷,那就在协议层处理分包和重组:

  • 在帧头里加一个“包序号”字段(1 字节)。
  • 加一个“是否最后一包”的标志位。
  • App 端按包序号拼接,校验缺失或乱序。

分包重组逻辑写起来不复杂,但在低功耗设备上尽量不要用,因为它会增加额外的处理开销和电量消耗。设计协议时,优先考虑“一次一帧”。

5.3 粘包与半包:串口和 BLE 都会遇到的难题

粘包是指多帧数据一次性被读到,半包是指一帧数据不完整。串口侧的程序员对这两件事不陌生,在 BLE 链路里也完全一样。

串口侧出现粘包的原因是串口接收中断太快,应用层还没来得及读取 FIFO,数据就已经连续到达。解决办法是:在串口接收回调里只做数据缓存,不清空时马上解析;主循环或专用解析任务里按帧格式去查头和长度。

BLE 侧出现粘包(连续几帧一次性到)的主要原因是 notify 的数据到达 App 时,底层可能做了批量递交。出现半包的原因是 MTU 太小导致一帧数据被拆成多个 notify。无论哪种情况,App 端的处理逻辑是一样的:用一个累积缓冲区,把收到的数据按字节流追加进去,然后反复尝试从缓冲区开头解析完整帧,解析出来的帧交给上层业务逻辑,剩余字节留在缓冲区里等下批数据。

这其实就是一套标准的 sticky/half packet 处理算法,写一次之后,在串口调试工具、Android App、iOS App 三个场景可以共用同一套代码逻辑,非常划算。

6. 常见问题与排查技巧实录

这条路走到这里,你已经知道了整体架构和每个环节的关键点。但实际项目的坑总是比教科书多,我把这几年调试各种串口 + BLE 设备时遇到的典型问题和排查思路整理了一下。希望能帮你减少一点踩坑时间。

6.1 连接不稳定、频繁断开

连接不稳定先看距离和干扰。BLE 在 2.4GHz 频段,和 Wi-Fi、USB 3.0、微波炉共享频谱。设备附近如果有大功率 Wi-Fi 路由器、USB 3.0 硬盘盒,干扰会非常明显。排查方法是:把手机放到设备旁边 10 厘米内,看断连频率是否下降。如果明显下降,就基本确认是干扰问题。

排除干扰后,看连接参数。如果连接间隔设置得太短(比如 7.5ms),同时设备处理能力不足,数据堆积会导致协议栈超时,连接就会断开。调试时,可以把超时时间设到 20 秒以上,这样即使链路短期拥塞,也不会轻易被判死。另外,注意设备端是否有频繁地进中断、关中断、忙等待导致协议栈事件得不到处理,这类问题需要在设备的主循环里保证 BLE 协议栈及时获得 CPU。

还有一类情况是手机端的蓝牙栈主动断连。Android 上某些系统省电策略会在设备长时间无有效数据交换时断开 BLE 连接。解决办法:应用层做一个“我的心跳数据包”,每隔几秒,设备主动发一个帧,保持链路活跃。实践证明,30 秒一次的心跳包足够。

6.2 数据丢帧、乱序

丢帧先分清楚是串口侧丢还是 BLE 侧丢。你可以在设备端写一个“自环测试”固件:把 BLE 收到的数据通过串口打印回来,同时统计发出和收回的字节数。如果串口侧收不全,问题在设备端的串口数据源或者单片机处理不及时,跟 BLE 无关。如果串口侧收得全,但 App 端丢数据,那问题出在 BLE 链路上。

BLE 侧丢帧的常见原因是 notify 发送过快导致缓冲区溢出。BLE 模组的 GATT 通知并不保证送达,它只是在每个连接事件里尽量发数据。如果连接间隔长、设备每一个连接事件发的包多,而模组缓冲区不够大,新数据会覆盖旧数据。解决办法:加应用层 ACK 机制,设备端在收到 App 的确认后再发下一批数据,但这种机制的实时性会下降,需要根据业务取舍。

乱序问题相对少见,BLE 底层通常保证连接事件内的数据包顺序,但多个连接事件之间的包在极端情况下可能乱序。在应用协议里给帧加序号,接收端对乱序帧做缓存和重排即可。我通常的做法是序号在初始化时随机生成,这样能避免从 0 开始的固定规律带来的安全问题。

6.3 功耗异常

很多设备接入 BLE 后发现待机电流大,这就是连接参数没配好。如果设备一直以 7.5ms 间隔维持连接,即使没数据要发,也要每个连接事件响应主机的空包查询,功耗自然高。正确的做法是,根据需求决定连接间隔。如果数据不频繁,从机延迟设到 4 以上,连接间隔拉到 100ms 甚至更大,设备大部分时间可以睡眠。

还要检查射频部分的功耗。一些 BLE 模组在空闲时会自动进入低功耗模式,前提是 MCU 不再通过 UART 发数据。如果 MCU 一直有数据发,比如某个传感器以 1 Hz 的频率不断上报,模组就一直处于活跃射频状态,电流下不去。在项目设计时,可以让 MCU 在无事件时主动关掉不用的外设和模组的射频,通过 GPIO 或指令控制。

6.4 调试工具组合

最后分享一套我一直在用的调试工具链,能帮你把串口侧、BLE 侧、App 侧分开排查:

  • 串口侧:SSCOM、Serial Port Assistant 这类工具,看设备到底发出来什么数据。注意有些工具的画面显示字节数不可靠,尽量用支持 hex 显示和保存 log 的工具。
  • BLE 侧:nRF Connect 是神器。手机装一个,扫描、连接、看 Service/Characteristic、手动写值、订阅 Notify 一目了然。遇到问题先拿它确认数据是不是真的从模组发出来了,再回去查 App 代码。
  • 协议分析:nRF Sniffer for Bluetooth LE,配合 Wireshark 抓空中的数据包。当蓝牙链路的行为比较诡异、又不想改代码加日志时,直接抓包分析连接参数、数据包重传、空包交互,能够快速找到问题源头。

这些工具不一定每个都用,但手里至少要有“串口助手 + nRF Connect”。几乎所有环境问题,都先在这两个工具上复现,再决定往哪边查。比起一上来就啃代码,效率高太多了。

就我个人经验来说,这类“串口到手机”的 BLE 项目,真正决定开发体验好坏的,不是某个技术难度特别高,而是链路中的每一跳都要严谨对待。串口侧不匹配、BLE 侧参数没调对、App 端订阅通知漏了写描述符,任何一环出问题,整个系统就完全不可用。调试时尽量做到分层隔离:先用串口助手确认 MCU 发出的数据正确,再用 nRF Connect 确认 BLE 模组的数据正确,最后才轮到写 App 逻辑。如果这三层的每一层都是干净的,那么整条链路肯定能通。后续做产品化,还可以在这个基础协议上加上 OTA 升级、多设备并行连接、云端中转等功能,但底层的数据通路设计,仍然是以这套思路为核心打底的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询