129 lines
5.7 KiB
Markdown
129 lines
5.7 KiB
Markdown
# RS485 扩展继电器板通信协议 V1.0
|
||
|
||
> 适用:控制终端(主控,V1.7.1 起)外接级联继电器扩展板(从机)。
|
||
> 从机板硬件/固件按本文档实现即可与主控直接对接。
|
||
|
||
## 1. 概述
|
||
|
||
主控板载 4 路继电器(sw1~sw4)不够用时,通过 RS485 总线级联一块扩展板,再扩 4 路带反馈继电器(平台标识符 sw5~sw8)。
|
||
|
||
- 主从结构:控制终端 = 主机(唯一主站),扩展板 = 从机
|
||
- 协议:**Modbus RTU**,从机地址固定 **0x10**(称重秤占用 0x01,勿冲突)
|
||
- 与称重秤**共用同一条 485 总线**(主控 USART2,PA2/PA3)
|
||
|
||
## 2. 物理层 / 总线规则
|
||
|
||
| 项 | 值 |
|
||
| --- | --- |
|
||
| 波特率 | 9600 bps,8N1 |
|
||
| 接口 | RS485 半双工 |
|
||
| 帧定界 | 空闲间隔(主控侧 DMA+IDLE,≥1 帧间隙判一帧) |
|
||
| **帧间隔** | **总线上任意两帧之间必须 ≥50ms**(从机 485 释放/回声沉降时间,实测踩过坑) |
|
||
| 应答时限 | 从机收到完整请求后 **≤100ms** 内应答(主机 300ms 超时,补发 1 次) |
|
||
| CRC | Modbus CRC16(多项式 0xA001,初值 0xFFFF),**低字节在前** |
|
||
|
||
## 3. 功能码
|
||
|
||
从机只需实现两个功能码:
|
||
|
||
### 3.1 FC05(0x05)写单线圈 —— 控制继电器
|
||
|
||
线圈地址 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 FC03(0x03)读保持寄存器 —— 状态/反馈/故障/版本
|
||
|
||
固定读 0x0000 起 4 个寄存器。
|
||
|
||
**请求(8 字节)**:`10 03 00 00 00 04 47 48`
|
||
|
||
**应答(13 字节)**:
|
||
|
||
| 字节 | 内容 |
|
||
| --- | --- |
|
||
| 0 | 0x10 |
|
||
| 1 | 0x03 |
|
||
| 2 | 0x08(数据字节数) |
|
||
| 3~4 | REG0:继电器输出状态,bit0~3 = 继电器 1~4(1=吸合) |
|
||
| 5~6 | REG1:反馈状态,bit0~3(1=负载得电) |
|
||
| 7~8 | REG2:故障标志,bit0~3(1=该路输出与反馈不一致持续 >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)
|
||
5. 只响应地址 0x10 的帧;**不要响应广播/其它地址**(总线上还有秤,地址 0x01)
|
||
6. 收帧间隔不足 50ms 也要能正常解析(主控保证发送间隔,从机只做鲁棒接收)
|
||
|
||
## 5. 主机行为(联调参考)
|
||
|
||
主控侧已实现(`HardWare/RELAY/ext_relay.c`):
|
||
|
||
- **命令流程**:平台/蓝牙下发 → FC05 → 等回显(300ms 超时,补发 1 次)→ 延时 150ms 等触点稳定 → FC03 读状态 → 校验"输出位=目标状态 且 故障位=0" → 应答平台 OK/失败 → 上报全状态
|
||
- **周期轮询**:空闲每 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. 联调检查清单
|
||
|
||
- [ ] 从机地址 0x10,9600-8N1
|
||
- [ ] FC05 回显与请求逐字节一致
|
||
- [ ] FC03 应答 13 字节,寄存器大端,状态位在低字节
|
||
- [ ] 应答延迟 ≤100ms
|
||
- [ ] 上电 4 路全断
|
||
- [ ] 拔掉反馈线后操作对应继电器,REG2 对应位约 1s 后置 1
|
||
- [ ] 与秤同时挂总线:主控发帧间隔 ≥50ms,两者互不丢帧
|