SSPC-Tester/Docs/Modbus接口规范/Modbus接口规范.md

252 lines
7.6 KiB
Markdown
Raw Permalink Normal View History

# Modbus 接口规范
## 1. 文档用途
本文档用于指导主项目接入已完成现场实测的 24 路继电器、电压采集和电流采集设备。
配套文件:
- `device-profile.json`:设备协议与通道映射的唯一权威配置。
- `appsettings.Modbus.example.json`:主项目默认配置字段示例。
- `接入验收清单.md`:开发完成后的测试和验收要求。
主项目实现时必须读取配置,不得在业务代码中硬编码从站地址、线圈、寄存器、量程、公式或通道映射。
## 2. 实测资料与结论
本规范依据以下现场结果整理:
- `结果_Modbus-接口-电流-电压对应表.txt`:逐个物理插位手动测量得到的采集页通道对应关系。
- `结果_modbus-tuner-20260618-131814.json`:调试程序于 2026-06-18 导出的已调通通讯参数。
编号含义必须严格区分:
| 名称 | 含义 |
|---|---|
| `physicalSlot` | 机器上的物理接口位置,也是主项目业务层唯一使用的通道号,范围 124 |
| `relayChannel` | 调试程序继电器控制页按钮号;实测与物理插位一致 |
| `sourceDisplayChannel` | 调试程序采集页面上出现读数的通道号,仅保留作实测追溯 |
| `registerOffset` | 在本次 24 寄存器回包数据区中的零基位置,主项目实际解析使用 |
主项目不得把 `sourceDisplayChannel` 当作物理插位,也不得直接用它计算字节偏移。
## 3. 总线与串口参数
所有模块共用一条 RS485 总线。
| 参数 | 实测值 |
|---|---|
| 协议 | Modbus RTU |
| 波特率 | 9600 |
| 数据位 | 8 |
| 校验 | None |
| 停止位 | 1 |
| 读取超时 | 500 ms |
| 失败重试 | 2 次 |
| CRC | CRC16-Modbus |
| CRC 字节序 | 低字节在前 |
| 地址、数量和寄存器数据 | 高字节在前 |
现场调试使用过 `COM9`,但 COM 号属于计算机本地设置。主项目应允许用户选择和保存,不得把 `COM9` 固定为设备协议的一部分。
同一串口的请求必须串行执行。不得让继电器写入、电压读取和电流读取同时向串口写帧。
## 4. 模块地址
| 模块 | 从站地址 |
|---|---:|
| 继电器板 1负责物理插位 18 | 1 |
| 继电器板 2负责物理插位 916 | 2 |
| 继电器板 3负责物理插位 1724 | 3 |
| 24 路电压采集模块 | 4 |
| 24 路电流采集模块 | 5 |
## 5. 继电器控制
使用功能码 `0x05` 写单个线圈。
- 开:`0xFF00`
- 关:`0x0000`
- 正常响应应回显请求中的从站、功能码、线圈地址和值。
- 响应必须检查长度、从站、功能码、回显内容和 CRC。
主项目业务接口建议:
```text
SetRelayAsync(int physicalSlot, bool isOn)
```
处理流程:
1. 校验 `physicalSlot` 为 124。
2.`device-profile.json``channels` 查找该物理插位。
3. 取得 `relay.slave``relay.coil`
4. 构造并发送 `0x05` 帧。
5. 验证回显后才更新业务状态。
不要在未确认当前硬件是否允许的情况下自动全开 24 路。
## 6. 电压采集
实测配置:
| 参数 | 值 |
|---|---|
| 从站 | 4 |
| 功能码 | `0x03` |
| 起始寄存器 | 0 |
| 寄存器数量 | 24 |
| 量程 | 100 V |
| 解析公式 | B |
| 公式 | `实际电压 = DATA / 100` |
| DATA 类型 | `UInt16` |
| 每通道字节数 | 2 |
| 数据字节序 | Big-Endian |
请求主体:
```text
04 03 00 00 00 18
```
追加 CRC16-Modbus 后发送。正常响应共 53 字节:
```text
[从站1][功能码1][字节数0x30][48字节数据][CRC2]
```
## 7. 电流采集
实测配置:
| 参数 | 值 |
|---|---|
| 从站 | 5 |
| 功能码 | `0x03` |
| 起始寄存器 | 0 |
| 寄存器数量 | 24 |
| 量程 | 60 A |
| 解析公式 | A |
| 公式 | `实际电流 = DATA / 10000 × 60` |
| DATA 类型 | `Int16` |
| 每通道字节数 | 2 |
| 数据字节序 | Big-Endian |
请求主体:
```text
05 03 00 00 00 18
```
这里的“带符号”按现场导出配置解释为:读取寄存器 023并将每个 16 位原始值按二进制补码转换为 `Int16`。主项目不得自行把起始寄存器改成 24也不得在映射地址上额外加 24。如后续更换硬件或重新标定应修改配置版本并重新验收。
## 8. 采集回包解析
电压和电流共用以下流程:
1. 检查响应最小长度。
2. 检查响应从站等于配置从站。
3. 检查功能码。若最高位为 1按 Modbus 异常响应处理。
4. 检查字节数为 `registerCount × registerBytes`,当前应为 48。
5. 验证 CRC16-Modbus。
6. 对每个物理插位读取对应的 `registerOffset`
7. 字节位置为:
```text
position = dataStartOffset + registerOffset × channelBytes
```
当前 `dataStartOffset=3``channelBytes=2`。
8. 按 Big-Endian 合成原始 16 位值。
9. 根据 `signed` 转换为 `UInt16``Int16`
10. 根据 `formula``range` 换算工程值。
公式定义:
```text
A: value = DATA / 10000.0 × range
B: value = DATA / range
```
## 9. 统一业务接口
主项目业务层只允许使用物理插位 124建议公开以下抽象
```text
ConnectAsync()
DisconnectAsync()
SetRelayAsync(int physicalSlot, bool isOn)
ReadAllVoltagesAsync()
ReadAllCurrentsAsync()
ReadMeasurementsAsync()
```
一次测量结果建议包含:
```text
PhysicalSlot
Voltage
Current
VoltageRaw
CurrentRaw
Timestamp
VoltageQuality
CurrentQuality
```
`ReadMeasurementsAsync()` 应分别完成一次电压整帧读取和一次电流整帧读取,再按 `physicalSlot` 合并。不要为每个物理插位单独读取一次寄存器;每种采集模块一次读取 24 个寄存器即可。
## 10. 配置加载与校验
程序启动时必须校验:
- `schemaVersion` 是程序支持的版本。
- 物理插位恰好覆盖 124不重复、不缺失。
- 继电器从站和线圈组合不重复。
- 电压、电流的 `registerOffset` 均在 `0registerCount-1`
- 每类采集映射不得出现重复的 `registerOffset`
- 从站地址范围为 1247。
- `registerBytes=2`、`channelBytes=2`。
- 公式只能是 `A``B`
- 字节序和 CRC 类型为程序支持值。
配置错误时应阻止通讯并给出具体字段,不要静默使用代码默认值。
## 11. 超时、重试和线程规则
- 一次请求从发送到收到完整响应视为一个事务。
- 失败后最多重试配置中的次数;当前为 2 次,即最多发送 3 次。
- CRC 错误、响应超时、从站错误、功能码错误和响应长度错误都应记录原始 HEX。
- 重试前应清理串口输入缓冲区,避免残帧与下一帧拼接。
- 串口操作使用互斥锁或单消费者队列串行化。
- 断开和应用退出时安全关闭串口。
## 12. 主项目配置建议
建议将机器本地参数放在主项目配置,将设备协议和映射放在独立配置:
```text
主项目配置
└─ Modbus
├─ Enabled
├─ PortName
├─ DeviceProfilePath
└─ PollIntervalMs
device-profile.json
├─ 串口通讯默认参数
├─ Modbus 帧规则
├─ 模块协议
└─ 24 路权威映射
```
`device-profile.json` 应随主程序发布并复制到输出目录。主项目可以提供配置界面修改 COM 口,但协议和通道映射只应由经过授权的维护流程更新。
## 13. AI 编程强制要求
将本目录交给主项目 AI 时,应附加以下要求:
> 严格按《Modbus接口规范.md》和 `device-profile.json` 实现。业务层统一使用 `physicalSlot` 124。所有从站、线圈、寄存器、量程、公式及映射从配置读取不得硬编码。`sourceDisplayChannel` 仅用于追溯现场实测不参与解析寻址。实现配置启动校验、串口事务串行化、CRC及响应完整校验并按《接入验收清单.md》完成测试。