shuichan_new/Docs/RS485扩展继电器协议.md

130 lines
6.4 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.

# RS485 扩展继电器板通信协议 V1.0
> 适用控制终端主控V1.7.1 起)外接级联继电器扩展板(从机)。
> 从机板硬件/固件按本文档实现即可与主控直接对接。
## 1. 概述
主控板载 4 路继电器sw1~sw4不够用时通过 RS485 总线级联一块扩展板,再扩 4 路带反馈继电器(平台标识符 sw5~sw8
- 主从结构:控制终端 = 主机(唯一主站),扩展板 = 从机
- 协议:**Modbus RTU**,从机地址固定 **0x10**(称重秤占用 0x01勿冲突
- 与称重秤**共用同一条 485 总线**(主控 USART2PA2/PA3
## 2. 物理层 / 总线规则
| 项 | 值 |
| --- | --- |
| 波特率 | 9600 bps8N1 |
| 接口 | RS485 半双工 |
| 帧定界 | 空闲间隔(主控侧 DMA+IDLE≥1 帧间隙判一帧) |
| **帧间隔** | **总线上任意两帧之间必须 ≥50ms**(从机 485 释放/回声沉降时间,实测踩过坑) |
| 应答时限 | 从机收到完整请求后 **≤100ms** 内应答(主机 300ms 超时,补发 1 次) |
| CRC | Modbus CRC16多项式 0xA001初值 0xFFFF**低字节在前** |
## 3. 功能码
从机只需实现两个功能码:
### 3.1 FC050x05写单线圈 —— 控制继电器
线圈地址 0~3 = 继电器 1~4对应平台 sw5~sw8
**请求8 字节)**
| 字节 | 内容 |
| --- | --- |
| 0 | 0x10从机地址 |
| 1 | 0x05功能码 |
| 2~3 | 线圈地址大端0x0000~0x0003 |
| 4~5 | 0xFF 0x00 = 吸合0x00 0x00 = 断开 |
| 6~7 | CRC16 低字节、高字节 |
**示例**:继电器 2 吸合 → `10 05 00 01 FF 00 DE BB`
**应答**:从机执行动作后**原样回显请求帧**。回显内容与请求不一致(线圈号/通断值不符)主机判失败。
### 3.2 FC030x03读保持寄存器 —— 状态/反馈/故障/版本
固定读 0x0000 起 4 个寄存器。
**请求8 字节)**`10 03 00 00 00 04 47 48`
**应答13 字节)**
| 字节 | 内容 |
| --- | --- |
| 0 | 0x10 |
| 1 | 0x03 |
| 2 | 0x08数据字节数 |
| 3~4 | REG0继电器输出状态bit0~3 = 继电器 1~41=吸合) |
| 5~6 | REG1反馈状态bit0~31=负载得电) |
| 7~8 | REG2故障标志bit0~31=该路输出与反馈不一致持续 >1s |
| 9~10 | REG3从机固件版本如 0x0100 = V1.0 |
| 11~12 | CRC16 低字节、高字节 |
寄存器 16 位大端;状态位放**低字节**即可,高字节填 0。
### 3.3 异常应答
从机遇到非法功能码/地址/数据时回标准 Modbus 异常帧:
`10 | (功能码 | 0x80) | 异常码 | CRC_lo | CRC_hi`(共 5 字节)
异常码0x01 非法功能0x02 非法地址0x03 非法数据。
## 4. 从机行为要求
1. **上电默认 4 路全部断开**(主控侧有断电记忆:每次离线→上线时,主控会比对 EEPROM 记忆状态与 REG0 实际状态,
不一致的回路会**逐路补发 FC05 纠正**——所以从机上线后紧跟着收到几条 FC05 属正常恢复流程,务必如实执行并回显)
2. FC05 收到并校验通过(地址/功能码/线圈范围/CRC后**立即执行**再回显
3. 反馈输入:每路继电器配负载反馈检测(同主控板载继电器:吸合后负载得电=高)。从机自行维护 REG2 故障位:某路输出状态与反馈不一致**持续超过 1s** 置 1恢复一致后清 0
4. 反馈采样建议 10~50ms 周期,加简单消抖(如连续 3 次一致才更新 REG1**消抖总时长必须 <150ms**——主控在 FC05 回显后 150ms 就读 FC03 校验反馈位反馈跟不上会误判"负载未通电"
5. 只响应地址 0x10 的帧**不要响应广播/其它地址**总线上还有秤地址 0x01
6. 收帧间隔不足 50ms 也要能正常解析主控保证发送间隔从机只做鲁棒接收
7. 主控**平时不发帧**无周期轮询只在控制命令和上电探测时通信从机不要把"长时间收不到帧"当异常处理
## 5. 主机行为(联调参考)
主控侧已实现`HardWare/RELAY/ext_relay.c`**平时总线零流量无周期轮询只在控制时检测**
- **上电探测**主控上电 3s 后发一次 FC03——有应答则标记在线并触发断电恢复比对无应答补发 1 次仍无记日志"未接扩展板?"不影响其它功能
- **命令流程**平台/蓝牙下发 **FC03 预读**判定在线 + 快照命令前反馈值无应答补发 1 仍无应答回平台 `ext relay board offline`)→ FC05 等回显300ms 超时补发 1 )→ 延时 150ms 等触点稳定 FC03 读状态 校验"输出位=目标 反馈位=目标 **反馈位有跳变**命令前目标与板载继电器反馈同语义重复命令原本已在目标态的豁免" 应答平台失败`Load unpowered / relay failure !`)→ 上报全状态
- **离线判定**命令链路最终无应答即判离线日志提示不单独周期监测下次命令第一步自动重新探测恢复应答即上线
- **断电记忆恢复**扩展板状态存在主控 EEPROM偏移 102 Relay_State[5]bit0~3每次离线上线时比对实际状态与记忆不一致的回路逐路补发 FC05 纠正恢复完成统一上报一次
- 上电 3s 内不发帧避开上电窗口
## 6. 平台/蓝牙映射
| | 映射 |
| --- | --- |
| MQTT 下发 | `iot.prop.set` **sw5~sw8**true/false扩展板在线时状态大报文携带 sw5~sw8 字段 |
| 平台应答 | 命令完成含反馈校验后回 `{"id":..,"code":0,"message":"OK"}` 或失败原因 |
| 蓝牙命令 | **R5ON ~ R8OFF**不应答平台只执行+记日志STATUS 显示扩展板状态 |
| 平台物模型 | 需新增 4 个布尔字段 sw5~sw8 |
## 7. CRC16 参考实现C
```c
static uint16_t crc16_modbus(const uint8_t *data, uint16_t len)
{
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < len; i++) {
crc ^= data[i];
for (uint8_t j = 0; j < 8; j++)
crc = (crc & 0x0001) ? ((crc >> 1) ^ 0xA001) : (crc >> 1);
}
return crc; /* 发送时低字节在前 */
}
```
## 8. 联调检查清单
- [ ] 从机地址 0x109600-8N1
- [ ] FC05 回显与请求逐字节一致
- [ ] FC03 应答 13 字节寄存器大端状态位在低字节
- [ ] 应答延迟 100ms
- [ ] 上电 4 路全断
- [ ] 拔掉反馈线后操作对应继电器REG2 对应位约 1s 后置 1
- [ ] 与秤同时挂总线主控发帧间隔 50ms两者互不丢帧