cs
public interface IPlcDevice :IDisposable
{
/// <summary>
/// PLC连接状态
/// </summary>
bool IsConnected { get; }
/// <summary>
/// 连接PLC
/// </summary>
/// <returns></returns>
bool Connect();
/// <summary>
/// 断开连接
/// </summary>
void Disconnect();
#region 同步读写方法
/// <summary>
/// 读取一个模块所有字节地址数据
/// </summary>
/// <param name="startByte"></param>
/// <param name="length"></param>
/// <returns></returns>
byte[] ReadDB6Bytes(int DBnum, int startByte, int length);
/// <summary>
/// 写字节
/// </summary>
/// <param name="startAddress"></param>
/// <param name="value"></param>
void WriteBytes(ushort startAddress, int value);
/// <summary>
/// 读取保持寄存器
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="numberOfPoints">长度</param>
/// <returns></returns>
ushort[] ReadHoldingRegisters(ushort startAddress, ushort numberOfPoints);
/// <summary>
/// 读取单个保存寄存器
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
ushort ReadSingleRegisters(ushort startAddress);
/// <summary>
/// 读取单个保存寄存器
/// </summary>
/// <param name="startAddress">地址</param>
/// <param name="s">位</param>
/// <returns></returns>
ushort ReadSingleRegisters(ushort startAddress, byte s);
/// <summary>
/// 读取线圈
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="numberOfPoints">长度</param>
/// <returns></returns>
bool[] ReadCoils(ushort startAddress, ushort numberOfPoints);
/// <summary>
/// 向指定位地址写值
/// </summary>
/// <param name="startAddress">字节地址</param>
/// <param name="bitAddress">位地址</param>
/// <param name="value">值</param>
void WriteSingleRegister(ushort address, ushort bitAddress, int value);
/// <summary>
/// 写单个寄存器
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">写入值</param>
void WriteSingleRegister(ushort address, ushort value);
/// <summary>
/// 写多个寄存器
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="values">写入值数组</param>
void WriteMultipleRegisters(ushort startAddress, ushort[] values);
/// <summary>
/// 写单个线圈
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">写入值</param>
void WriteSingleCoil(ushort address, bool value);
/// <summary>
/// 读取32位长整型数
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
int ReadInt32(ushort startAddress);
/// <summary>
/// 写入32位整型数
/// </summary>
/// <param name="startAddress">地址</param>
/// <param name="value">写入值</param>
void WriteInt32(ushort startAddress, int value);
/// <summary>
/// 读取浮点数
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
float ReadFloat(ushort startAddress);
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="wordLength">字长度</param>
/// <param name="encoding">编码格式</param>
/// <returns></returns>
string ReadString(ushort startAddress, ushort wordLength = 20, Encoding encoding = null);
/// <summary>
/// 读取字符串,自动判断编码格式
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="wordLength">字长度</param>
/// <returns></returns>
string ReadStringAutoDetect(ushort startAddress, ushort wordLength = 20);
/// <summary>
/// 写入字符串
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="text">写入文本</param>
/// <param name="encoding">编码格式</param>
void WriteString(ushort startAddress, string text, Encoding encoding = null);
#endregion
#region 异步读写方法
/// <summary>
/// 异步读取db模块所有字节地址
/// </summary>
/// <param name="dbNumber"></param>
/// <param name="startByte"></param>
/// <param name="length"></param>
/// <returns></returns>
Task<byte[]> ReadBytesAsync(int dbNumber, int startByte, int length);
/// <summary>
/// 异步读单个保持寄存器
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
Task<ushort> ReadSingleRegistersAsync(ushort startAddress);
/// <summary>
/// 异步写单个保持寄存器
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">写入值</param>
/// <returns></returns>
Task WriteSingleRegisterAsync(ushort address, ushort value);
/// <summary>
/// 异步读浮点数
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
Task<float> ReadFloatAsync(ushort startAddress);
/// <summary>
/// 异步写浮点数
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">写入值</param>
/// <returns></returns>
Task WriteFloatAsync(ushort address, float value);
/// <summary>
/// 异步读32位整数
/// </summary>
/// <param name="startAddress">地址</param>
/// <returns></returns>
Task<int> ReadInt32Async(ushort startAddress);
/// <summary>
/// 异步写32位整数
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">写入值</param>
/// <returns></returns>
Task WriteInt32Async(ushort address, int value);
/// <summary>
/// 异步读取字符串
/// </summary>
/// <param name="startAddress">地址</param>
/// <param name="wordLength">字长度</param>
/// <param name="encoding">解码方式</param>
/// <returns></returns>
Task<string> ReadStringAsync(ushort startAddress, ushort wordLength = 20, Encoding encoding = null);
/// <summary>
/// 异步写字符串
/// </summary>
/// <param name="startAddress">地址</param>
/// <param name="text">写入文本</param>
/// <returns></returns>
Task WriteStringAsync(ushort startAddress,string text, Encoding encoding = null);
#endregion
}
cs
using NPOI.SS.Formula.Functions;
using NPOI.XSSF.Streaming.Values;
using S7.Net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
using DataType = S7.Net.DataType;
namespace Aliro.Agv.HardWare
{
public class SimaticS7Net : IPlcDevice
{
//DataType.DataBlock, 1:
//对于 S7-200 SMART,其 V 存储区被映射为 DB1。所以当你访问 V 区时,DataType 是 DataBlock,db 参数是 1。
//例如,VB100 的地址是 DataType.DataBlock, 1, 100, VarType.Byte, 1。
// 注意注意:如果按照字或者双字访问,地址必须按照双数的方式访问
//地址计算:
//startByte 参数是字节地址。VW102 表示从第102个字节开始的一个字(2字节),所以 startByte 是 102。
//bitAdr 参数是位地址(0-7),只在读写 VarType.Bit 时使用。
//数据类型和转换:
//PLC 中的数据类型(如 WORD, DWORD)需要与 C# 中的类型(ushort, uint)正确匹配,特别是处理无符号数时。
//注意字节序(大端序),S7NetPlus 会自动处理转换。
//错误处理:
//务必使用 try-catch 块包裹所有读写操作,因为网络不稳定或 PLC 停机都会导致异常。
//在操作前检查 plc.IsConnected 状态。
//常见错误:
//ErrorNumber : 0x8324:通常表示 IP 地址错误、网络不通或 PLC 未正确启用 GET/PUT 通信。
//Object reference not set to an instance of an object:plc 对象未初始化。
//写入值后读取不一致:检查 PLC 程序中是否有其他地方(如逻辑程序)在重写你正在操作的数据区。
private Plc _plc;
private string _ipAddress;
private CpuType _cpuType = CpuType.S71200;
public short DbNo = 6;
public short Rack = 1;
public short Slot = 1;
public bool IsConnected => _plc.IsConnected == true;
public SimaticS7Net(string ipAddress, CpuType _cpuType, short dbNo = 1, short rack = 0, short slot = 1)
{
_ipAddress = ipAddress;
this._cpuType = _cpuType; // CPU类型
_plc = new Plc(_cpuType, _ipAddress, rack, slot); // 机架号0,槽号1
DbNo = dbNo;
Rack = rack;
Slot = slot;
}
public bool Connect()
{
try
{
if (_plc == null)
{
_plc = new Plc(_cpuType, _ipAddress, Rack, Slot);
}
_plc.Open();
if (_plc.IsConnected)
{
//Console.WriteLine("成功连接到 PLC (S7协议)");
return true;
}
else
{
//Console.WriteLine("连接失败");
return false;
}
}
catch (Exception ex)
{
//Console.WriteLine($"连接失败: {ex.Message}");
return false;
}
}
public void Disconnect()
{
try
{
_plc?.Close();
_plc = null;
//Console.WriteLine("已断开与 PLC 的连接");
}
catch (Exception ex)
{
//Console.WriteLine($"断开连接时出错: {ex.Message}");
}
}
public void Dispose()
{
Disconnect();
#region 读数据示例
//// 读取一个布尔值(位)从 V100.0 (V区,字节100,位0)
//bool boolValue = (bool)_plc?.Read(DataType.DataBlock, 1, 100, VarType.Bit, 1);
//Console.WriteLine($"V100.0 (Bool) 的值是: {boolValue}");
//// 读取一个字节 (8位) 从 VB101
//byte byteValue = (byte)_plc?.Read(DataType.DataBlock, 1, 101, VarType.Byte, 1);
//Console.WriteLine($"VB101 (Byte) 的值是: {byteValue}");
//// 读取一个16位整数 (Int) 从 VW102
//short shortValue = (short)_plc?.Read(DataType.DataBlock, 1, 102, VarType.Word, 1);
//// 注意:PLC中的VW102对应C#的short(Int16),并且是高位字节在前(大端序)
//Console.WriteLine($"VW102 (Int) 的值是: {shortValue}");
//// 读取一个32位整数 (DInt) 从 VD104
//int intValue = (int)_plc?.Read(DataType.DataBlock, 1, 104, VarType.DInt, 1);
//Console.WriteLine($"VD104 (DInt) 的值是: {intValue}");
//// 读取一个32位浮点数 (Real) 从 VD108
//float floatValue = (float)_plc?.Read(DataType.DataBlock, 1, 108, VarType.Real, 1);
//Console.WriteLine($"VD108 (Real) 的值是: {floatValue}");
//// 读取一个字符串从 VB200 (最大长度20)
//// 字符串在PLC中通常第一个字节是最大长度,第二个字节是实际长度,后面是字符数据
//string stringValue = (string)_plc?.Read(DataType.DataBlock, 1, 108, VarType.String, 20);
//Console.WriteLine($"VB200 (String) 的值是: {stringValue}");
#endregion
#region 写数据示例
//// 写入一个布尔值(位)到 V100.1
//_plc.WriteBit(DataType.DataBlock, 1, 100, 1, true); // 将 V100.1 设置为 True
//Console.WriteLine("已写入 V100.1 = True");
//// 写入一个字节到 VB101
//_plc.Write(DataType.DataBlock, 1, 101, (byte)123);
//Console.WriteLine("已写入 VB101 = 123");
//// 写入一个16位整数到 VW102
//_plc.Write(DataType.DataBlock, 1, 102, (short)-4567);
//Console.WriteLine("已写入 VW102 = -4567");
//// 写入一个32位整数到 VD104
//_plc.Write(DataType.DataBlock, 1, 104, 789012);
//Console.WriteLine("已写入 VD104 = 789012");
//// 写入一个32位浮点数到 VD108
//_plc.Write(DataType.DataBlock, 1, 108, 123.45f);
//Console.WriteLine("已写入 VD108 = 123.45");
//// 写入一个字符串到 VB200
//// 注意:S7NetPlus的WriteString方法会自动处理最大长度和实际长度字节
//_plc.Write(DataType.DataBlock, 1, 200, "Hello from C#!");
//Console.WriteLine("已写入字符串到 VB200");
#endregion
}
#region 新增
// 读取 DB6 中的所有字
public byte[] ReadDB6Bytes(int DBnum, int startByte, int length)
{
try
{
if (!_plc.IsConnected)
{
Console.WriteLine("PLC 未连接");
return null;
}
// 读取 DB6 中的数据块
// 参数说明: DataBlockNumber, startByte, dataType, length
var result = _plc.ReadBytes(DataType.DataBlock, DBnum, startByte, length);
if (result == null || result.Length != length)
{
Console.WriteLine($"读取失败或数据长度不正确");
return null;
}
return result;
}
catch (Exception ex)
{
Console.WriteLine($"读取数据时出错: {ex.Message}");
return null;
}
}
#endregion
public bool[] ReadCoils(ushort startAddress, ushort numberOfPoints)
{
throw new InvalidOperationException("未连接到PLC");
}
public float ReadFloat(ushort startAddress)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
return (float)_plc.Read(DataType.DataBlock, DbNo, startAddress, VarType.Real, 1);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public ushort[] ReadHoldingRegisters(ushort startAddress, ushort numberOfPoints)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
var objValue = _plc.Read(DataType.DataBlock, DbNo, startAddress, VarType.Word, numberOfPoints);
if (objValue is ushort[] result)
{
return result;
}
else
{
return null;
}
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public ushort ReadSingleRegisters(ushort startAddress)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
var result = (ushort)_plc.Read(DataType.DataBlock, DbNo, startAddress, VarType.Word, 1);
return result;
}
catch (Exception ex)
{
Console.WriteLine($"读取寄存器失败: {ex.Message}");
throw;
}
}
public ushort ReadSingleRegisters(ushort startAddress, byte s = 0)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
var result = (ushort)_plc.Read(DataType.DataBlock, DbNo, startAddress, VarType.Bit, 1, s);
return result;
}
catch (Exception ex)
{
Console.WriteLine($"读取寄存器失败: {ex.Message}");
throw;
}
}
public int ReadInt32(ushort startAddress)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
//
var value = _plc.Read(DataType.DataBlock, DbNo, startAddress, VarType.DInt, 1);
return Convert.ToInt32(value);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public string ReadString(ushort startAddress, ushort wordLength = 20, Encoding encoding = null)
{
if (!IsConnected || _plc == null)
throw new InvalidOperationException("未连接到PLC");
if (encoding == null)
encoding = Encoding.ASCII;
try
{
// 读取一个字符串从 VB
// 字符串在PLC中通常第一个字节是字符长度,后面是字符数据
var str = (string)_plc?.Read(DataType.DataBlock, DbNo, startAddress, VarType.String, wordLength * 2);
//var objValue = _plc?.Read(DataType.DataBlock, 1, startAddress, VarType.Byte, wordLength * 2);
//// 移除首字节
//byte[] strBytes = (byte[])objValue;
//var strASCII = encoding.GetString((byte[])strBytes);
// 截取有效字符串
int index = str.IndexOf('\r');
var subStr = str;
if (index > 0)
{
subStr = str.Substring(1, index - 1);
}
else
{
// 以0作为结束付
int length = subStr.Length;
for (int i = 0; i < subStr.Length; i++)
{
if (subStr[i] == 0x00)
{
length = i;
break;
}
}
subStr = str.Substring(1, length - 1);
}
//// 读取保持寄存器(每个寄存器2个字节)
//ushort[] registers = _modbusMaster.ReadHoldingRegisters(_slaveId, startAddress, wordLength);
//// 将寄存器数组转换为字节数组
//byte[] byteData = ConvertRegistersToBytesCDAB(registers);
////// 将字节数组转换为字符串
////var str = GlobalFunction.byteToHexStr(byteData);
//// 转换为字符串(自动处理终止符)
//var str = ConvertBytesToString(byteData, encoding);
return subStr;
}
catch (Exception ex)
{
Console.WriteLine($"读取字符串失败: {ex.Message}");
throw;
}
}
public string ReadStringAutoDetect(ushort startAddress, ushort wordLength = 20)
{
throw new NotImplementedException();
}
public void WriteInt32(ushort startAddress, int value)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
_plc.Write(DataType.DataBlock, DbNo, startAddress, value);
}
catch (Exception ex)
{
Console.WriteLine($"写入寄存器失败: {ex.Message}");
throw;
}
}
public void WriteBytes(ushort startAddress, int value)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
byte[] BT = new byte[1] { 0x01};
_plc.WriteBytes(DataType.DataBlock,6,0,BT);
}
catch (Exception ex)
{
Console.WriteLine($"写入寄存器失败: {ex.Message}");
throw;
}
}
public void WriteMultipleRegisters(ushort startAddress, ushort[] values)
{
throw new NotImplementedException();
}
public void WriteSingleCoil(ushort address, bool value)
{
throw new NotImplementedException();
}
public void WriteSingleRegister(ushort address, ushort value)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
_plc.Write(DataType.DataBlock, DbNo, address, value);
}
catch (Exception ex)
{
Console.WriteLine($"写入寄存器失败: {ex.Message}");
throw;
}
}
public void WriteSingleRegister(ushort address, ushort bitAddress, int value)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
_plc.Write(DataType.DataBlock, DbNo, address, value, bitAddress);
}
catch (Exception ex)
{
Console.WriteLine($"写入寄存器失败: {ex.Message}");
throw;
}
}
public void WriteString(ushort startAddress, string text, Encoding encoding = null)
{
if (!IsConnected || _plc == null)
throw new InvalidOperationException("未连接到PLC");
if (encoding == null)
encoding = Encoding.ASCII;
try
{
// 写入一个字符串到 VB
// 注意:S7NetPlus的WriteString方法会自动处理最大长度和实际长度字节
_plc.Write(DataType.DataBlock, DbNo, startAddress, text);
//// 将字符串转换为字节数组
//byte[] byteData = encoding.GetBytes(text);
//// 确保字节数为偶数(补齐)
//if (byteData.Length % 2 != 0)
//{
// Array.Resize(ref byteData, byteData.Length + 1);
// byteData[byteData.Length - 1] = 0x00; // 用空字符填充
//}
//// 将字节数组转换为寄存器数组
//ushort[] registers = ConvertBytesToRegisters(byteData);
//// 写入PLC
//_modbusMaster.WriteMultipleRegisters(_slaveId, startAddress, registers);
}
catch (Exception ex)
{
Console.WriteLine($"写入字符串失败: {ex.Message}");
throw;
}
}
#region 异步读写方法
public async Task<byte[]> ReadBytesAsync(int dbNumber, int startByte, int length)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
var r = _plc.ReadBytes(DataType.DataBlock, dbNumber, startByte, length);
return r;
}
catch
{
return null;
}
}
public async Task<ushort> ReadSingleRegistersAsync(ushort startAddress)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
var t = await _plc.ReadAsync(DataType.DataBlock, DbNo, startAddress, VarType.Word, 1);
return Convert.ToUInt16(t);
}
catch (Exception ex)
{
Console.WriteLine($"读取寄存器失败: {ex.Message}");
throw;
}
}
public async Task WriteSingleRegisterAsync(ushort address, ushort value)
{
if (!IsConnected || _plc == null)
{
throw new InvalidOperationException("未连接到PLC");
}
try
{
await _plc.WriteAsync(DataType.DataBlock, DbNo, address, value);
}
catch (Exception ex)
{
Console.WriteLine($"写入寄存器失败: {ex.Message}");
throw;
}
}
public async Task<float> ReadFloatAsync(ushort startAddress)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
var t = await _plc.ReadAsync(DataType.DataBlock, DbNo, startAddress, VarType.Real, 1);
return Convert.ToSingle(t);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public async Task WriteFloatAsync(ushort startAddress, float value)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
await _plc.WriteAsync(DataType.DataBlock, DbNo, startAddress, value);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public async Task<int> ReadInt32Async(ushort startAddress)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
var t = await _plc.ReadAsync(DataType.DataBlock, DbNo, startAddress, VarType.DInt, 1);
return Convert.ToInt32(t);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public async Task WriteInt32Async(ushort startAddress, int value)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
await _plc.WriteAsync(DataType.DataBlock, DbNo, startAddress, value);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public async Task<string> ReadStringAsync(ushort startAddress, ushort wordLength = 20, Encoding encoding = null)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
// 读取一个字符串从 VB
// 字符串在PLC中通常第一个字节是字符长度,后面是字符数据
var objValue = await _plc?.ReadAsync(DataType.DataBlock, DbNo, startAddress, VarType.String, wordLength * 2);
var str = Convert.ToString(objValue);
//var objValue = _plc?.Read(DataType.DataBlock, 1, startAddress, VarType.Byte, wordLength * 2);
//// 移除首字节
//byte[] strBytes = (byte[])objValue;
//var strASCII = encoding.GetString((byte[])strBytes);
// 截取有效字符串
int index = str.IndexOf('\r');
var subStr = str;
if (index > 0)
{
subStr = str.Substring(1, index - 1);
}
else
{
// 以0x00作为结束符
int length = subStr.Length;
for (int i = 0; i < subStr.Length; i++)
{
if (subStr[i] == 0x00)
{
length = i;
break;
}
}
subStr = str.Substring(1, length - 1);
}
return subStr;
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
public async Task WriteStringAsync(ushort startAddress, string text, Encoding encoding = null)
{
if (!IsConnected || _plc == null) throw new Exception("未连接到 PLC");
try
{
await _plc.WriteAsync(DataType.DataBlock, DbNo, startAddress, text);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
throw;
}
}
#endregion
}
}
这是一个基于 S7.Net 库实现的西门子 PLC(S7-1200/1500 等)通信类
核心属性
-
IsConnected:检查 PLC 连接状态
-
DbNo:默认的数据块编号(默认为 6)
-
Rack/Slot:PLC 的机架号和槽号
连接管理
-
Connect():连接到 PLC,返回连接是否成功
-
Disconnect():断开与 PLC 的连接
-
Dispose():实现 IDisposable 接口,清理资源
同步读取方法
-
ReadFloat():从指定地址读取 32 位浮点数(Real 类型)
-
ReadInt32():从指定地址读取 32 位整数(DInt 类型)
-
ReadSingleRegisters():从指定地址读取单个 16 位寄存器(Word 类型)
- 两个重载版本:一个读取字,一个读取位(bit)
-
ReadHoldingRegisters():批量读取多个 16 位寄存器
-
ReadString():从指定地址读取字符串(String 类型),自动处理字符串终止符
-
ReadDB6Bytes():读取数据块的原始字节数组(方法名固定为 DB6,但参数支持任意 DB 块)
同步写入方法
- WriteSingleRegister():
-
写入单个 16 位寄存器(Word)
-
重载版本支持写入位(bit)
-
WriteInt32():写入 32 位整数(DInt)
-
WriteBytes():写入字节数组(目前代码中硬编码为 DB6,地址 0)
-
WriteString():写入字符串到 PLC
异步方法(Async 后缀)
-
ReadSingleRegistersAsync():异步读取单个寄存器
-
ReadFloatAsync():异步读取浮点数
-
ReadInt32Async():异步读取 32 位整数
-
ReadStringAsync():异步读取字符串
-
WriteSingleRegisterAsync():异步写入单个寄存器
-
WriteFloatAsync():异步写入浮点数
-
WriteInt32Async():异步写入 32 位整数
-
WriteStringAsync():异步写入字符串
未实现方法
-
ReadCoils():读取线圈(不支持,抛出异常)
-
WriteSingleCoil():写入单个线圈(不支持)
-
WriteMultipleRegisters():批量写入寄存器(未实现)
-
ReadStringAutoDetect():自动检测字符串(未实现)
特点说明
-
地址映射 :所有方法都通过
DataType.DataBlock访问数据块 -
错误处理:每个方法都包含连接状态检查和异常处理
-
字符串处理:自动处理 PLC 字符串格式(长度字节+字符数据)
-
字节序处理 :S7.Net 库自动处理大端序/小端序转换
-
异步支持:提供了完整的异步读写方法
使用方法
cs
var plc = new SimaticS7Net("192.168.1.1", CpuType.S71200);
plc.Connect();
// 读取数据
float temp = plc.ReadFloat(100); // 读取 DB6.DBD100
string name = plc.ReadString(200, 20); // 读取 DB6.DBB200 开始的字符串
// 写入数据
plc.WriteSingleRegister(300, 1234); // 写入 DB6.DBW300 = 1234
plc.WriteString(400, "Hello PLC"); // 写入字符串到 DB6.DBB400
plc.Disconnect();