Siemens S7
Zeus 的 S7 模块支持 Siemens S7 TCP,也就是常见的 ISO-on-TCP / Read Var / Write Var 访问方式。当前覆盖 DB、I、Q、M 区的 Bool、Byte、Word、DWord、Int、DInt 和 Real,并支持点表采集、按点名写回和虚拟 PLC 联调。
安装
dotnet add package Zeus.Communications
dotnet add package Zeus.Protocols.S7
连接真实 PLC
S7 TCP 通常使用端口 102。通道只负责 TCP 收发,S7 设备挂在通道之上:
await using var app = ZeusHost.Create(builder =>
{
builder.AddTcpClient("plc-link", "192.168.1.10", 102);
builder.AddSiemensS7("plc", "plc-link", new S7Options
{
Rack = 0,
Slot = 1
});
});
await app.StartAsync();
var plc = app.Devices.Get<S7Device>("plc");
var temperature = await plc.ReadRealAsync(S7Area.DataBlock, byteOffset: 0, dbNumber: 1);
await plc.WriteIntAsync(S7Area.DataBlock, byteOffset: 4, value: 120, dbNumber: 1);
var running = await plc.ReadBoolAsync(S7Area.Merkers, byteOffset: 10, bitOffset: 0);
如果现场使用 S7-300/400,槽号常见为 2;S7-1200/1500 项目常见为 1。Zeus 默认 Rack = 0、Slot = 1,不匹配时请显式设置。
读写常用类型
var dbBytes = await plc.ReadDataBlockBytesAsync(dbNumber: 1, byteOffset: 0, length: 8);
await plc.WriteDataBlockBytesAsync(dbNumber: 1, byteOffset: 20, values: [1, 2, 3, 4]);
var word = await plc.ReadWordAsync(S7Area.DataBlock, 0, dbNumber: 1);
var dint = await plc.ReadDIntAsync(S7Area.DataBlock, 4, dbNumber: 1);
var real = await plc.ReadRealAsync(S7Area.DataBlock, 8, dbNumber: 1);
var bit = await plc.ReadBoolAsync(S7Area.DataBlock, 12, 3, dbNumber: 1);
await plc.WriteWordAsync(S7Area.Merkers, 0, 1234);
await plc.WriteBoolAsync(S7Area.Outputs, 2, 1, true);
S7 多字节数值按 PLC 常用的大端字节序编码。Bool 使用字节偏移加位偏移,例如 DB1.DBX12.3 对应 area: db、db: 1、address: 12、bit: 3。
点表采集与写回
await using var app = ZeusHost.Create(builder =>
{
builder.AddTcpClient("plc-link", "192.168.1.10", 102);
builder.AddSiemensS7("plc", "plc-link", points: map => map
.DbReal("temperature", dbNumber: 1, byteOffset: 0)
.DbInt("setpoint", dbNumber: 1, byteOffset: 4, scale: 0.1).Writable("setpoint")
.MarkerBool("running", byteOffset: 10, bitOffset: 0).Writable("running"));
});
await app.StartAsync();
var temperature = app.Points.Get<float>("temperature");
await app.Points.WriteAsync("setpoint", 12.3);
await app.Points.WriteAsync("running", true);
scale 用于整数寄存器的工程值换算。上例中写入 12.3 会反算为原始 123 再写入 DB1.DBW4。
没硬件时先跑虚拟 PLC
var memory = new S7SlaveMemory();
await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("plc-link", new S7SlaveResponder(memory));
builder.AddSiemensS7("plc", "plc-link");
});
await app.StartAsync();
var plc = app.Devices.Get<S7Device>("plc");
await plc.WriteRealAsync(S7Area.DataBlock, 0, 25.5f, dbNumber: 1);
var value = await plc.ReadRealAsync(S7Area.DataBlock, 0, dbNumber: 1);
虚拟 PLC 支持 S7 握手、Read Var 和 Write Var,可用于测试主站逻辑、界面绑定和 JSON 配置。
可运行示例:samples/Zeus.Samples.Console.S7。该示例使用虚拟 S7 PLC,演示 DB/M 区点表采集、点名写回和直接协议读写。
JSON 配置
真实 PLC:
{
"channels": [
{ "name": "plc-link", "type": "tcp", "host": "192.168.1.10", "port": 102 }
],
"devices": [
{
"name": "plc",
"channel": "plc-link",
"type": "siemens-s7",
"rack": 0,
"slot": 1,
"points": [
{ "name": "temperature", "area": "db", "db": 1, "address": 0, "dataType": "real" },
{ "name": "setpoint", "area": "db", "db": 1, "address": 4, "dataType": "int", "scale": 0.1, "writable": true },
{ "name": "running", "area": "m", "address": 10, "bit": 0, "dataType": "bool", "writable": true }
]
}
]
}
无硬件联调:
{
"channels": [
{ "name": "plc-link", "type": "virtual", "responder": "s7" }
],
"devices": [
{
"name": "plc",
"channel": "plc-link",
"type": "siemens-s7",
"points": [
{ "name": "temperature", "area": "db", "db": 1, "address": 0, "dataType": "real" }
]
}
]
}
常见问题
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 一直超时 | IP、端口 102、rack/slot 或 PLC 访问设置不对 | 先用 S7SlaveResponder 跑通主站,再核对现场参数 |
| DB 能读但值不对 | DB 偏移、数据类型或优化访问设置不匹配 | 对照 TIA Portal 的实际地址,确认 DB 地址可被外部访问 |
| Bool 点不对 | 忘了 bit 偏移 | address 是字节偏移,bit 是 0–7 |
| 写输入区失败 | I 区由 PLC 输入映像驱动 | 写 Q、M 或 DB 区;I 区只读 |