跳到主要内容

三菱 MC

Zeus 的 MC 模块支持 Mitsubishi MC Protocol 1E / 3E / 4E,适合通过以太网读写三菱 PLC 的常用软元件。默认使用 3E Binary;也可以切到 ASCII 编码或 1E / 4E 帧。当前覆盖 X/Y/M 位软元件、D/W/R/ZR 字软元件,以及 3E / 4E 随机读写。

安装

dotnet add package Zeus.Communications
dotnet add package Zeus.Protocols.Mc

连接真实 PLC

MC 通常跑在 TCP 通道上。通道只负责搬运字节,协议设备挂在通道之上:

await using var app = ZeusHost.Create(builder =>
{
builder.AddTcpClient("plc-link", "192.168.1.10", 5000);
builder.AddMitsubishiMc("plc", "plc-link");
});

await app.StartAsync();

var plc = app.Devices.Get<McDevice>("plc");
var d100 = await plc.ReadDataRegistersAsync(address: 100, points: 2);
var y20 = await plc.ReadOutputRelaysAsync(address: 0x20, points: 8);
await plc.WriteDataRegistersAsync(address: 200, values: [123, 456]);
await plc.WriteOutputRelaysAsync(address: 0x20, values: [true, false, true, false]);

AddMitsubishiMc3E 仍然保留,等价于默认 3E Binary。新代码推荐用更通用的 AddMitsubishiMc

如果现场 PLC 的帧类型、编码、网络号、PC 号、I/O 号或站号不是默认值,可以传入 Mc3EOptions

builder.AddMitsubishiMc("plc", "plc-link", new Mc3EOptions
{
FrameType = McFrameType.Frame3E,
DataEncoding = McDataEncoding.Binary,
NetworkNumber = 0x00,
PcNumber = 0xFF,
IoNumber = 0x03FF,
StationNumber = 0x00,
MonitoringTimer = 0x0010
});

常见切换方式:

// 3E ASCII
builder.AddMitsubishiMc("plc", "plc-link", new Mc3EOptions
{
FrameType = McFrameType.Frame3E,
DataEncoding = McDataEncoding.Ascii
});

// 4E Binary / ASCII,可按需设置序列号
builder.AddMitsubishiMc("plc", "plc-link", new Mc3EOptions
{
FrameType = McFrameType.Frame4E,
DataEncoding = McDataEncoding.Binary,
SerialNumber = 0x0001
});

// 1E Binary / ASCII,主要用于较旧设备或旧配置
builder.AddMitsubishiMc("plc", "plc-link", new Mc3EOptions
{
FrameType = McFrameType.Frame1E,
DataEncoding = McDataEncoding.Ascii
});

读写常用软元件

常用 API 已按三菱软元件名包装:

var d = await plc.ReadDataRegistersAsync(100, 4);
await plc.WriteDataRegistersAsync(100, [10, 20, 30, 40]);

var m = await plc.ReadInternalRelaysAsync(100, 8);
await plc.WriteInternalRelaysAsync(100, [true, false, true, false]);

var x = await plc.ReadInputRelaysAsync(0x10, 8);
var y = await plc.ReadOutputRelaysAsync(0x20, 8);
await plc.WriteOutputRelaysAsync(0x20, [true, false, true, false]);

var w = await plc.ReadLinkRegistersAsync(100, 2);
await plc.WriteLinkRegistersAsync(100, [1000, 1001]);

var r = await plc.ReadFileRegistersAsync(100, 2);
await plc.WriteFileRegistersAsync(100, [2000, 2001]);

var zr = await plc.ReadExtendedFileRegistersAsync(100, 2);
await plc.WriteExtendedFileRegistersAsync(100, [3000, 3001]);

需要直接按软元件代码调用时,也可以使用泛型读写方法:

var words = await plc.ReadWordsAsync(McDeviceCode.DataRegister, 100, 2);
var bits = await plc.ReadBitsAsync(McDeviceCode.InternalRelay, 100, 8);
await plc.WriteBitsAsync(McDeviceCode.InputRelay, 0x40, [true, false, true]);

真实 PLC 上 X 输入继电器通常由现场输入状态驱动,便捷 API 只提供读取;如果设备或仿真环境允许写入,可使用通用 WriteBitsAsync

随机读写

3E / 4E 帧支持在一次事务中访问多个不连续软元件。随机读取可同时返回单字和双字结果;随机写入按 MC 协议分为字/双字写入和位写入:

var random = await plc.ReadRandomAsync(
wordDevices:
[
new McDeviceAddress(McDeviceCode.DataRegister, 100),
new McDeviceAddress(McDeviceCode.LinkRegister, 10)
],
doubleWordDevices:
[
new McDeviceAddress(McDeviceCode.DataRegister, 200)
]);

var d100 = random.WordValues[0];
var w10 = random.WordValues[1];
var d200D201 = random.DoubleWordValues[0];

await plc.WriteRandomWordsAsync(
wordValues:
[
new McWordWrite(McDeviceCode.DataRegister, 110, 1234),
new McWordWrite(McDeviceCode.LinkRegister, 11, 5678)
],
doubleWordValues:
[
new McDoubleWordWrite(McDeviceCode.DataRegister, 210, 0x12345678)
]);

await plc.WriteRandomBitsAsync(
[
new McBitWrite(McDeviceCode.InternalRelay, 100, true),
new McBitWrite(McDeviceCode.OutputRelay, 0x20, false)
]);

随机读写仅适用于 3E / 4E;1E 帧继续支持上面的连续批量读写。

没 PLC 时先联调

McSlaveResponder 可以挂到虚拟通道上,模拟一个 MC PLC。它会自动识别 1E / 3E / 4E 和 Binary / ASCII 请求:

var memory = new McSlaveMemory();
memory.DataRegisters[100] = 1234;
memory.InternalRelays[10] = true;

await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("plc-link", new McSlaveResponder(memory));
builder.AddMitsubishiMc("plc", "plc-link");
});

这样可以先验证业务代码、界面绑定和通信追踪,再把虚拟通道换成 AddTcpClient

用 JSON 配置

安装 Zeus.Configuration 后,可以把通道和 MC 设备放进 zeus.json

{
"channels": [
{
"name": "plc-link",
"type": "tcp",
"host": "192.168.1.10",
"port": 5000
}
],
"devices": [
{
"name": "plc",
"channel": "plc-link",
"type": "mitsubishi-mc",
"frameType": "4e",
"encoding": "ascii",
"serialNumber": 1,
"networkNumber": 0,
"pcNumber": 255,
"ioNumber": 1023,
"stationNumber": 0,
"monitoringTimer": 16,
"points": [
{ "name": "temperature", "deviceCode": "D", "address": 100, "scale": 0.1, "writable": true },
{ "name": "run", "deviceCode": "M", "address": 10, "writable": true },
{ "name": "ready", "deviceCode": "X", "address": "0x10" },
{ "name": "recipe", "deviceCode": "ZR", "address": 0 }
]
}
]
}

程序里读取后仍然从设备目录取 McDevice

await using var app = ZeusHost.Create(builder => builder.AddJsonFile("zeus.json"));
await app.StartAsync();

var plc = app.Devices.Get<McDevice>("plc");
var d100 = await plc.ReadDataRegistersAsync(100, 2);

声明 points 后会自动接入周期采集和点表写回:

var temperature = app.Points.Get<double>("temperature");
await app.Points.WriteAsync("run", true);
await app.Points.WriteAsync("temperature", 12.3);

MC 点使用 deviceCode 指定软元件:DMXYWRZR。其中 X 输入继电器只读,不能设置 writable: true;ZR 仅 3E / 4E 支持。地址可以写十进制数,也可以写字符串形式的十六进制,例如 "0x10"

无硬件时可以把通道改成虚拟 MC PLC:

{
"name": "plc-link",
"type": "virtual",
"responder": "mc"
}

JSON 已支持声明和热更新 MC 设备,也支持 MC points 点表映射、周期采集和按点名写回。

当前范围

能力状态
3E Binary / ASCII 帧已支持
4E Binary / ASCII 帧已支持
1E Binary / ASCII 帧已支持常用批量读写;1E 不支持原始 ExecuteAsync 命令
D 数据寄存器批量读写已支持
M 内部继电器批量读写已支持
X 输入继电器批量读取已支持
Y 输出继电器批量读写已支持
W 链接寄存器批量读写已支持
R 文件寄存器批量读写已支持
ZR 扩展文件寄存器批量读写3E / 4E 已支持
随机读取、随机字/双字写入、随机位写入3E / 4E 已支持
JSON 点表 / 周期采集 / 点名写回已支持
虚拟 PLC / 无硬件联调已支持

常见问题

现象最可能原因处理
连接失败IP、端口、防火墙或 PLC 以太网设置不对先确认 TCP 端口能连通
返回结束码地址越界、软元件类型不支持或 PLC 拒绝访问McException.EndCode,再对照 PLC 手册
读到的数据错位地址基准和设备文档不一致确认 D100 是否应直接写 address: 100;X/Y 常按十六进制编号理解,例如 X10 可写 "address": "0x10"
一直超时PLC 未启用对应 MC 帧型、编码或端口不是 MC 协议McSlaveResponder 先确认主站代码,再核对 FrameType / DataEncoding

下一步:需要标准 Modbus 设备看 Modbus,需要私有帧看 自定义帧