# 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`。