Files
STM8_Mesh_Control/docs/HOST_PROTOCOL_SPEC.md
T
十七 be8bd7eaec docs: 修正Mesh发送与接收帧格式说明
明确41 54 2B AA A1为所有发送方统一使用的发送格式,F1 DD 09 00 0A为接收方UART侧接收格式,并同步修正源码注释。
2026-11-03 11:32:24 +08:00

476 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STM8 Mesh 继电器主机通信协议
本文档供主机、网关和上位机开发人员使用。通信分为两层:JDY-28M Mesh外层和设备业务内层。
## 1. Mesh外层帧
### 1.1 主机发送给设备
```text
41 54 2B AA A1 | DST_H DST_L | A0 | BUSINESS | 0D 0A
```
字段说明:
| 字段 | 长度 | 说明 |
|---|---:|---|
| `41 54 2B AA A1` | 5 | JDY-28M Mesh发送固定帧头 |
| `DST_H DST_L` | 2 | 目标短地址,高字节在前 |
| `A0` | 1 | Mesh数据通信标志,固定值 |
| `BUSINESS` | 变长 | 本文档第2节定义的业务帧 |
| `0D 0A` | 2 | Mesh帧尾,固定值 |
广播地址:
```text
FFFF
```
单播到短地址`000C`:
```text
DST_H = 00
DST_L = 0C
```
### 1.2 接收端串口收到的 Mesh 数据格式
```text
F1 DD 09 00 0A | SRC_H SRC_L | BUSINESS | 0D 0A
```
这是接收方 UART 侧看到的接收格式,不是设备或主机发送时使用的格式。
其中两字节是 JDY-28M 接收帧中携带的地址字段;业务发送方短地址仍然放在
业务帧 `BUSINESS` 的 `SRC_H SRC_L` 字段中。
无论发送方是主机还是设备,发送时都统一使用第1.1节的格式:
```text
41 54 2B AA A1 | DST_H DST_L | A0 | BUSINESS | 0D 0A
```
### 1.3 长度限制
JDY-28M完整Mesh帧最大20字节。当前业务帧最大DATA长度为4字节:
```text
BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_L CRC16_H
```
业务帧长度为`6 + LEN`,完整外层发送帧长度为`16 + LEN`,因此`LEN`最大为4。
## 2. 业务帧格式
```text
SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_L CRC16_H
```
### 2.1 CRC16规则
```text
算法:CRC-16/MODBUS
多项式:0xA001
初始值:0xFFFF
输入反射:是
输出反射:是
计算范围:SRC_H、SRC_L、CMD、LEN和DATA
发送顺序:CRC低字节在前,高字节在后
```
CRC错误时设备直接丢弃整帧,不执行命令,也不返回错误应答。
## 3. 通用应答规则
普通请求的应答命令通常为:
```text
应答CMD = 请求CMD | 0x80
```
错误应答:
```text
CMD = E0
LEN = 01
DATA[0] = 错误码
```
当前常用错误码:
```text
0x02:DATA长度错误
0x03:DATA参数错误
0x05:EEPROM或配置写入失败
0x06:未知命令
```
## 4. 主机下发的普通命令
### 4.1 `0x01` 继电器控制
主机发送:
```text
CMD = 01
LEN = 01
DATA[0] = 00:继电器断开
DATA[0] = 01:继电器吸合
```
业务帧结构示例:
```text
SRC_H SRC_L 01 01 01 CRC16_L CRC16_H
```
设备执行后返回:
```text
CMD = 81
LEN = 01
DATA[0] = 当前继电器控制状态
```
```text
00:断开
01:吸合
```
注意:当前没有继电器触点反馈,设备只能确认PA1控制输出已经设置,不能确认触点机械动作是否真实成功。电流异常由故障检测功能另行上报。
### 4.2 `0x02` 查询继电器状态
主机发送:
```text
CMD = 02
LEN = 00
```
设备返回:
```text
CMD = 82
LEN = 01
DATA[0] = 00:断开
DATA[0] = 01:吸合
```
### 4.3 `0x03` 查询实际电流
主机发送:
```text
CMD = 03
LEN = 00
```
设备返回:
```text
CMD = 83
LEN = 02
DATA[0] = 电流低字节
DATA[1] = 电流高字节
```
单位为mA,无符号整数,低字节在前。例如实际电流为`1000mA = 0x03E8`:
```text
DATA = E8 03
```
### 4.4 `0x05` 查询设备短地址
主机发送:
```text
CMD = 05
LEN = 00
```
设备返回:
```text
CMD = 85
LEN = 02
DATA[0] = 短地址高字节
DATA[1] = 短地址低字节
```
例如设备短地址为`000C`:
```text
DATA = 00 0C
```
### 4.5 `0x06` 配置电流阈值
主机发送:
```text
CMD = 06
LEN = 02
DATA[0] = 阈值低字节
DATA[1] = 阈值高字节
```
单位为mA,默认值为100mA,设备保存到内部EEPROM。例如设置100mA:
```text
DATA = 64 00
```
设备成功返回:
```text
CMD = 86
LEN = 02
DATA = 原样返回设置的阈值
```
## 5. 固件版本查询
### 5.1 `0x0E` 查询当前固件版本
主机发送:
```text
CMD = 0E
LEN = 00
```
设备返回:
```text
CMD = 8E
LEN = 02
DATA[0] = 版本低字节
DATA[1] = 版本高字节
```
当前版本在主程序`include/app_config.h`中定义:
```c
#define FIRMWARE_VERSION 0x0001u
```
例如版本`0x0001`返回:
```text
DATA = 01 00
```
## 6. 故障与恢复上报
故障上报由设备主动发送:
```text
CMD = 04
LEN = 01
DATA[0] = 故障码或恢复码
```
故障码:
```text
0x00:继电器吸合但持续无有效电流
0x01:继电器断开但仍存在持续电流
0x02:ACS712采样异常
0x03:蓝牙初始化异常,仅LED指示,不通过Mesh上报
0x04:电流故障恢复
0x05:蓝牙故障恢复
0x06:采样异常恢复
0x07:继电器控制失败预留码
```
主机确认故障或恢复上报:
```text
CMD = 84
LEN = 01
DATA[0] = 被确认的故障码或恢复码
```
故障产生和恢复都需要持续至少10秒确认。故障恢复上报未收到主机确认时,设备每10秒重复上报,直到收到确认。
## 7. OTA命令
主机发送的OTA固件是`mesh_relay.bin`裸二进制文件,不是HEX文本文件,也不包含Bootloader。
### 7.1 `0x08` 进入OTA
```text
CMD = 08
LEN = 04
DATA[0] = 固件长度低字节
DATA[1] = 固件长度高字节
DATA[2] = 版本号低字节
DATA[3] = 版本号高字节
```
设备收到后擦除:
```text
OTA固件区:0x020000~0x02FFFF
OTA元数据:0x030000~0x030FFF
```
成功应答:
```text
CMD = 88
LEN = 01
DATA[0] = 00
```
### 7.2 `0x09` 固件分包
正常数据包:
```text
CMD = 09
LEN = 04
DATA[0] = OFFSET高字节
DATA[1] = OFFSET低字节
DATA[2] = 固件数据1
DATA[3] = 固件数据2
```
最后只有1字节固件数据时:
```text
CMD = 09
LEN = 03
DATA[0] = OFFSET高字节
DATA[1] = OFFSET低字节
DATA[2] = 固件数据1
```
设备只接受等于当前期待偏移的分包。成功后返回:
```text
CMD = 89
LEN = 03
DATA[0] = 00:写入成功
DATA[1] = 下一期待偏移高字节
DATA[2] = 下一期待偏移低字节
```
如果偏移错误、Flash写入失败或OTA状态错误,返回非0状态码。主机应根据返回的期待偏移重传。
### 7.3 `0x0A` 发送完整固件CRC16
```text
CMD = 0A
LEN = 02
DATA[0] = 完整固件CRC16低字节
DATA[1] = 完整固件CRC16高字节
```
CRC16使用CRC-16/MODBUS,计算范围是整个裸二进制固件文件。
设备接收后返回:
```text
CMD = 8A
LEN = 01
DATA[0] = 00:接收成功
```
### 7.4 `0x0B` 请求校验并提交升级
主机发送:
```text
CMD = 0B
LEN = 00
```
设备从W25Q64重新读取完整固件并计算CRC16。校验成功后写入OTA元数据:
```text
0x030000:魔数
0x030004:固件长度
0x030008:固件版本
0x03000A:CRC16
0x03000E:镜像有效标志0xA5
0x03000F:升级请求0xA5
```
设备返回:
```text
CMD = 8B
LEN = 01
DATA[0] = 00:校验成功,已提交升级
DATA[0] = 01:校验失败
```
之后设备复位,由Bootloader把OTA固件搬运到内部Flash的`0x8800`区域。
### 7.5 `0x0C` 取消OTA
主机发送:
```text
CMD = 0C
LEN = 00
```
设备返回:
```text
CMD = 8C
LEN = 01
DATA[0] = 00:取消成功
```
### 7.6 OTA传输顺序
```text
查询版本:0E
进入OTA:08
等待应答:88
发送分包:09
每包等待应答:89
发送完整CRC16:0A
请求校验提交:0B
等待校验结果:8B
设备复位并升级
主程序启动后主动上报升级结果:0D
主机确认升级结果:8D
```
## 8. OTA升级结果上报
设备启动后从`0x030010`读取升级结果,蓝牙初始化成功后主动广播:
```text
CMD = 0D
LEN = 01
DATA[0] = 升级结果码
```
结果码:
```text
0x00:无结果
0x01:升级成功
0x02:固件CRC错误
0x03:内部Flash写入失败
0x04:写入后校验失败
0x05:固件长度非法
0x06:W25Q64读取失败
```
主机确认:
```text
CMD = 8D
LEN = 01
DATA[0] = 对应的升级结果码
```
设备收到确认后清除`0x030010`。