SMARTWATCH 学习手册有 C 基础 · 嵌入式从零开始
支线二 / CH582M 开发与蓝牙桥接 / 07

把蓝牙接口与应用协议逐层对上

最后把两种“协议”放在各自的位置:蓝牙库负责连接和特征访问,应用协议说明这些字节代表什么。用一份实际电量消息,从主控一直追踪到手机显示。

接续上一篇:STM32 发出之后,怎样成为蓝牙通知

1 · 两层约定分别回答什么问题

层次回答的问题本项目约定
蓝牙访问接口连谁、写哪里、从哪里收SmartWatch、FFE0、FFE2、FFE3、通知订阅
应用消息格式字节的含义和边界是什么0xAA 帧头、长度、命令、数据、校验
业务处理收到有效消息后做什么显示电量、更新设置、传输原型等

蓝牙服务不会因为某字节是 0xAA 就识别为电量。相反,即使消息校验规则完全一致,手机写错了特征,也到不了对应业务处理。调试时必须明确自己在检查哪一层。

2 · 从一条七字节电量帧开始

协议中的示例帧 · 所有字节为十六进制

AA 06 03 A0 0F 3C 62

这里消息类型为 06,载荷长度为 03;数据中的 A0 0F 按低字节在前表示 0x0FA0,即 4000 毫伏,3C 表示 60。AA、06、03、A0、0F、3C 相加为 0x19E;取负数后保留低八位,得到校验 62。把校验也加进去,低八位应为零。精确格式以 协议规范 为准。

STM32 生成这组字节,从串口发出;CH 接收、排队、通知;App 解析以后才把它变成“4000 mV”。CH 桥接代码无需认识毫伏或电池百分比。

3 · 同一组字节可以分几次到达

假设手机两次收到 AA 06 03 和 A0 0F 3C 62。第一次只有帧的一部分,解析器应保存它;第二次补齐后再校验和输出消息。若下一条帧紧跟在后面,也应该继续从剩余字节解析。

这解释了为何本支线不在 CH 中按通知长度补帧头,也不因为串口出现接收超时就判断一帧结束。传输分块与业务分帧各自解决一个问题。主线已写过解析器,App 支线会把相同规则接到通知流。

4 · 三端逐项核对,避免只看最终界面

看到的现象先检查什么
手机扫描不到CH 是否启动、广播和扫描响应
能连接但没有写入入口服务发现结果、UUID、写属性
手机写后 STM32 收不到FFE2 回调、队列拒绝、UART1 配置和交叉接线
STM32 发了但手机无通知串口接收、事件处理、FFE3 订阅、连接状态
有通知但数值不对字节流组帧、长度、校验、字段单位和端序

每次只推进一个观测点,例如先确认 STM32 接收字节正确,再处理命令响应。不要同时改 UUID、串口参数和消息格式,导致无法判断哪一步产生效果。

5 · 完成这一支线以后怎样继续

现在能够说明每个方向的函数调用、数据存储与接收条件。继续进入支线三,使用 Dart 与 Flutter 把服务发现、订阅、帧解析和界面状态连起来。AI 和个性化支线随后使用这条已有通道传业务内容。

参考 CH 模块说明、三端协议 与 App 蓝牙实现 做对照。生产代码本次不作改写。

动手观察

完成一次双向联调记录:发了哪组字节、经过哪些函数、手机是否订阅、实际 MTU、是否收到应用响应。再检查低 MTU、队列积压与断开重连;没有设备时只记录源码核对结果,不写成真机通过。

资料与代码