西门子PLC通信
西门子DB
DB 为数据块,就是DATA BLOCK 的两个单词的简写。
DB100是数据块编号为100,DBX0.0:就是在数据块中,第一个字节的第一个位。
DB100.DBX0.0 完整的意思:在数据块100中,第一个字节的第一个位
1、DB100.DBB0 一个字节有8个位,分别为0---7!例:0.0----0.7共8位。
2、DB100.DBW0一个字有两个字节,分别为 DB100.DBB0和 DB100.DBB1
3、DB100.DBD0一个双字有两个字,分别为 DB100.DBW0和 DB100.DBW2
4、DB100.DBX0.0 一个位,这是最小单位。
数据块位表示用DBX 1位 1bit
数据块字节表示用DBB 8位 1byde
数据块字表示用DBW 16位
数据块双字表示用DBD 32位
Bit => DB1.DBX0.0
Byte => DB1.DBB0
word => DB1.DBW0
DWord => DB1.DBD0
Int => DB1.DBW0
DInt => DB1.DBD0
Real => DB1.DBD0
C#与西门子类型转换
Bit => bool
Byte => byte
//S7 Word (无符号短整型, 16位)
word => ushort
//S7 DWord (无符号长整型, 32位)
DWord => uint
//S7 Int / Dec (有符号短整型, 16位)
Int => short
//S7 Dint (有符号长整型, 32位)
DInt => int
//S7 Real (浮点数, 32位IEEE 754格式)
Real => float
LReal => double
String => string
S7.NET
//1、建立连接
CpuType cpuType = (CpuType)Enum.Parse(typeof(CpuType), XHText.Text, true);
//PLC类型、IP、rack、slot
myplc = new Plc(cpuType, IPText.Text, short.Parse(JTHText.Text.ToString()), short.Parse(CCHText.Text.ToString()));
myplc.Open();
//2、断开连接
myplc.Close();
//3、数据读取
var Value = myplc.Read(DZText1.Text.ToUpper());
//Bit => bool
OutValue = ((bool)Value).ToString();
//Byte => byte
OutValue = ((byte)Value).ToString();
//word => ushort
OutValue = ((ushort)Value).ConvertToShort().ToString();
//DWord => uint
OutValue = ((uint)Value).ConvertToInt().ToString();
//Int => short
OutValue = ((ushort)Value).ConvertToShort().ToString();
//DInt => int
OutValue = ((uint)Value).ConvertToInt().ToString();
//Real => float
OutValue = ((uint)Value).ConvertToDouble().ToString();
//4、数据写入
//Bit => bool
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToBoolean(WriteText.Text.ToString().ToUpper()));
//Byte => byte
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToByte(WriteText.Text.ToString().ToUpper()));
//word => ushort
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToUInt16(WriteText.Text.ToString().ToUpper()));
//DWord => uint
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToUInt32(WriteText.Text.ToString().ToUpper()));
//Int => short
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToUInt16(WriteText.Text.ToString().ToUpper()));
//DInt => int
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToUInt32(WriteText.Text.ToString().ToUpper()));
//Real => float
OutValue = ((uint)Value).ConvertToDouble().ToString();
myplc.Write(XRDZText1.Text.ToString().ToUpper(), Convert.ToUInt32(WriteText.Text.ToString().ToUpper()));
C#与西门子PLC的S7.net通信 - 知乎 (zhihu.com)
.net通过S7.net读写西门子PLC中,字符串,bool,整数,小数及byte型_西门子的数组类型地址位怎么读-CSDN博客
C#使用S7.net连接西门子S1200PLC,C#直接连接西门子PLC_c#与plc通讯-CSDN博客
ReadBytes
类型转换
//byte
return bytes[0];
//ushort
return Word.FromByteArray(bytes);
//short
return Int.FromByteArray(bytes);
//uint
return DWord.FromByteArray(bytes);
//int
return DInt.FromByteArray(bytes);
//float
return S7.Net.Types.Single.FromByteArray(bytes);
//string 读取时需要往后移动两字节
S7.Net.Types.String.FromByteArray(bytes);
//bool
return Bit.FromByte(bytes[0], bitAdr);
读取方式
注意:西门子两个string之间需要最少预留1字节空间
//读取地址形式 DB1.DBX1.1
public object? Read(string variable)
{
PLCAddress pLCAddress = new PLCAddress(variable);
return Read(pLCAddress.DataType, pLCAddress.DbNumber, pLCAddress.StartByte, pLCAddress.VarType, 1, (byte)pLCAddress.BitNumber);
}
//地址解析 DB1.DBX
public PLCAddress(string address)
{
Parse(address, out dataType, out dbNumber, out varType, out startByte, out bitNumber);
}
public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
{
//根据数据类型获取长度
int count = VarTypeToByteLength(varType, varCount);
//读取字节数据
byte[] bytes = ReadBytes(dataType, db, startByteAdr, count);
return ParseBytes(varType, bytes, varCount, bitAdr);
}
//长度计算
private int VarTypeToByteLength(VarType varType, int varCount = 1)
{
switch (varType)
{
case VarType.Bit:
return varCount;
case VarType.Byte:
if (varCount >= 1)
{
return varCount;
}
return 1;
case VarType.String:
return varCount;
case VarType.StringEx:
return varCount + 2;
case VarType.Word:
case VarType.Int:
case VarType.Timer:
case VarType.Counter:
return varCount * 2;
case VarType.DWord:
case VarType.DInt:
case VarType.Real:
return varCount * 4;
case VarType.DateTime:
return varCount * 8;
case VarType.DateTimeLong:
return varCount * 12;
default:
return 0;
}
}
//读取数据
public byte[] ReadBytes(DataType dataType, int db, int startByteAdr, int count)
{
byte[] array = new byte[count];
int num = 0;
while (count > 0)
{
int num2 = Math.Min(count, MaxPDUSize - 18);
ReadBytesWithSingleRequest(dataType, db, startByteAdr + num, array, num, num2);
count -= num2;
num += num2;
}
return array;
}
//类型转换
private object? ParseBytes(VarType varType, byte[] bytes, int varCount, byte bitAdr = 0)
{
if (bytes == null || bytes.Length == 0)
{
return null;
}
switch (varType)
{
case VarType.Byte:
if (varCount == 1)
{
return bytes[0];
}
return bytes;
case VarType.Word:
if (varCount == 1)
{
return Word.FromByteArray(bytes);
}
return Word.ToArray(bytes);
case VarType.Int:
if (varCount == 1)
{
return Int.FromByteArray(bytes);
}
return Int.ToArray(bytes);
case VarType.DWord:
if (varCount == 1)
{
return DWord.FromByteArray(bytes);
}
return DWord.ToArray(bytes);
case VarType.DInt:
if (varCount == 1)
{
return DInt.FromByteArray(bytes);
}
return DInt.ToArray(bytes);
case VarType.Real:
if (varCount == 1)
{
return S7.Net.Types.Single.FromByteArray(bytes);
}
return S7.Net.Types.Single.ToArray(bytes);
case VarType.String:
return S7.Net.Types.String.FromByteArray(bytes);
case VarType.StringEx:
return StringEx.FromByteArray(bytes);
case VarType.Timer:
if (varCount == 1)
{
return Timer.FromByteArray(bytes);
}
return Timer.ToArray(bytes);
case VarType.Counter:
if (varCount == 1)
{
return Counter.FromByteArray(bytes);
}
return Counter.ToArray(bytes);
case VarType.Bit:
if (varCount == 1)
{
if (bitAdr > 7)
{
return null;
}
return Bit.FromByte(bytes[0], bitAdr);
}
return Bit.ToBitArray(bytes, varCount);
case VarType.DateTime:
if (varCount == 1)
{
return S7.Net.Types.DateTime.FromByteArray(bytes);
}
return S7.Net.Types.DateTime.ToArray(bytes);
case VarType.DateTimeLong:
if (varCount == 1)
{
return DateTimeLong.FromByteArray(bytes);
}
return DateTimeLong.ToArray(bytes);
default:
return null;
}
}
写入方式
//根据Value的类型转化为byte[]
Serialization.SerializeValue(value);
//写入数据byte[]
public void WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
{
int num = 0;
int num2 = value.Length;
while (num2 > 0)
{
int num3 = Math.Min(num2, MaxPDUSize - 28);
WriteBytesWithASingleRequest(dataType, db, startByteAdr + num, value, num, num3);
num2 -= num3;
num += num3;
}
}
//Example
WriteBytes(dataType, db, startByteAdr, Serialization.SerializeValue(value));
//value转换为byte[]
public static byte[] SerializeValue(object value)
{
switch (value.GetType().Name)
{
case "Boolean":
return new byte[1] { (byte)(((bool)value) ? 1u : 0u) };
case "Byte":
return S7.Net.Types.Byte.ToByteArray((byte)value);
case "Int16":
return Int.ToByteArray((short)value);
case "UInt16":
return Word.ToByteArray((ushort)value);
case "Int32":
return DInt.ToByteArray((int)value);
case "UInt32":
return DWord.ToByteArray((uint)value);
case "Double":
return S7.Net.Types.Double.ToByteArray((double)value);
case "Single":
return S7.Net.Types.Single.ToByteArray((float)value);
case "DateTime":
return S7.Net.Types.DateTime.ToByteArray((System.DateTime)value);
case "Byte[]":
return (byte[])value;
case "Int16[]":
return Int.ToByteArray((short[])value);
case "UInt16[]":
return Word.ToByteArray((ushort[])value);
case "Int32[]":
return DInt.ToByteArray((int[])value);
case "UInt32[]":
return DWord.ToByteArray((uint[])value);
case "Double[]":
return S7.Net.Types.Double.ToByteArray((double[])value);
case "Single[]":
return S7.Net.Types.Single.ToByteArray((float[])value);
case "String":
{
string obj = (string)value;
return S7.Net.Types.String.ToByteArray(obj, obj.Length);
}
case "DateTime[]":
return S7.Net.Types.DateTime.ToByteArray((System.DateTime[])value);
case "DateTimeLong[]":
return DateTimeLong.ToByteArray((System.DateTime[])value);
default:
throw new InvalidVariableTypeException();
}
}
//写入Bit
public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{
if (bitAdr < 0 || bitAdr > 7)
{
throw new InvalidAddressException($"Addressing Error: You can only reference bitwise locations 0-7. Address {bitAdr} is invalid");
}
WriteBitWithASingleRequest(dataType, db, startByteAdr, bitAdr, value);
}
//写入Bit
public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
{
if (value < 0 || value > 1)
{
throw new ArgumentException("Value must be 0 or 1", "value");
}
WriteBit(dataType, db, startByteAdr, bitAdr, value == 1);
}
//写入S7String
var temp = Encoding.ASCII.GetBytes(val);
var bytes = S7.Net.Types.S7String.ToByteArray(val, temp.Length);
_plc.WriteBytes(dataType, dbNumber, address, bytes);
public void WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
{
int num = 0;
int num2 = value.Length;
while (num2 > 0)
{
int num3 = Math.Min(num2, MaxPDUSize - 28);
WriteBytesWithASingleRequest(dataType, db, startByteAdr + num, value, num, num3);
num2 -= num3;
num += num3;
}
}
private void WriteBytesWithASingleRequest(DataType dataType, int db, int startByteAdr, byte[] value, int dataOffset, int count)
{
try
{
Stream streamIfAvailable = GetStreamIfAvailable();
byte[] array = BuildWriteBytesPackage(dataType, db, startByteAdr, value, dataOffset, count);
streamIfAvailable.Write(array, 0, array.Length);
ValidateResponseCode((ReadWriteErrorCode)COTP.TSDU.Read(streamIfAvailable)[14]);
}
catch (Exception innerException)
{
throw new PlcException(ErrorCode.WriteData, innerException);
}
}
private static object GetVariableValue(VarType varType, string text)
{
switch (varType)
{
case VarType.Bit:
return bool.Parse(text);
case VarType.Byte:
return byte.Parse(text);
case VarType.Word:
return ushort.Parse(text);
case VarType.DWord:
return uint.Parse(text);
case VarType.Int:
return short.Parse(text);
case VarType.DInt:
return int.Parse(text);
case VarType.Real:
return float.Parse(text);
case VarType.LReal:
return double.Parse(text);
default:
return null;
}
}
//bool
WriteBit(dataType, db, startByteAdr, bitAdr, value2);
WriteBytes(dataType, db, startByteAdr, Serialization.SerializeValue(value));
异常
S7PlcDataManager封装的String读取PLC时字节长度+1,S7String读取PLC时字节长度+2,都是在头部添加字符串长度.
采用S7Sstring类型读取和写入PLC中字符串

浙公网安备 33010602011771号