6.0 KiB
6.0 KiB
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. 从机行为要求
- 上电默认 4 路全部断开(主控侧有断电记忆:每次离线→上线时,主控会比对 EEPROM 记忆状态与 REG0 实际状态, 不一致的回路会逐路补发 FC05 纠正——所以从机上线后紧跟着收到几条 FC05 属正常恢复流程,务必如实执行并回显)
- FC05 收到并校验通过(地址/功能码/线圈范围/CRC)后立即执行再回显
- 反馈输入:每路继电器配负载反馈检测(同主控板载继电器:吸合后负载得电=高)。从机自行维护 REG2 故障位:某路输出状态与反馈不一致持续超过 1s 置 1,恢复一致后清 0
- 反馈采样建议 10~50ms 周期,加简单消抖(如连续 3 次一致才更新 REG1);消抖总时长必须 <150ms——主控在 FC05 回显后 150ms 就读 FC03 校验反馈位,反馈跟不上会误判"负载未通电"
- 只响应地址 0x10 的帧;不要响应广播/其它地址(总线上还有秤,地址 0x01)
- 收帧间隔不足 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)
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,两者互不丢帧