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

129 lines
5.9 KiB
Markdown
Raw Normal View History

# 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 也要能正常解析(主控保证发送间隔,从机只做鲁棒接收)
## 5. 主机行为(联调参考)
主控侧已实现(`HardWare/RELAY/ext_relay.c`
- **命令流程**:平台/蓝牙下发 → FC05 → 等回显300ms 超时,补发 1 次)→ 延时 150ms 等触点稳定 → FC03 读状态 → 校验"输出位=目标状态 **且 反馈位=目标状态**"(与板载继电器反馈同语义,失败应答 `Load unpowered / relay failure !`)→ 应答平台 → 上报全状态
- **周期轮询**:空闲每 2s 发一次 FC03兼在线检测连续 3 次无应答判离线(日志提示)
- **断电记忆恢复**:扩展板状态存在主控 EEPROM偏移 102 的 Relay_State[5]bit0~3每次离线→上线时比对实际状态与记忆不一致的回路逐路补发 FC05 纠正,恢复完成统一上报一次
- **离线行为**:离线期间下发命令直接回复平台 "ext relay board offline";板子恢复应答后自动上线并补一次状态上报
- 上电 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两者互不丢帧