S7通信协议是西门子S7系列PLC内部集成的一种通信协议,它是一种运行在传输层之上的(会话层/表示层/应用层)、经过特殊优化的通信协议,其信息传输可以基于MPI网络、PROFIBUS网络或者以太网。
S7.Net 通信库提供了S7协议通信的常用方法:创建、打开、关闭、读写数据。
S7.Net安装:右击项目---管理Nuget程序包----搜索S7.Net
,选择S7netplus
,安装即可。
创建连接
仿真设备环境:
// ip地址 port端口号 rack机架号 0 slot插槽 1 cpuType 型号
string ip = "192.168.80.133";
int port = 102;
short rack = 0;
short slot = 1;
// 不同cpu型号机架号和插槽不一样
CpuType cpuType = CpuType.S71500;
//创建plc实例
plc = new Plc(cpuType, ip, port, rack, slot);
// 打开连接
if(plc != null) {
plc.Open();
// 读或写操作
// 关闭连接
plc.Close();
}
读数据
数据块定义的变量:
IQM区定义的变量:
plc中监控的数据:
方式一:字符串地址读取
DB2.DBX0.0
按拉访问
DB2:数据块表名称。
访问方式:X(bit) 位,B(byte) 字节,W(word) 字,D(DWord) 双字。
0.0:第一个0是读取的字节的开始位置,偏移量值;第二个0是位的地址。
var val1= plc.Read("DB2.DBX0.0"); // true
DB2.DBW6
按字访问
var val2 = plc.Read("DB2.DBW6"); // 120
DB2.DBX1.3
字节中按拉读取
var val3 = plc.Read("DB2.DBX1.3"); // true
DB2.DBD2
按双字读取
// 读float数据
var val4 = plc.Read("DB2.DBD2"); // 1104412672
// 转成byte[]
byte[] arrVal4= BitConverter.GetBytes((uint)val4);
// byte[]转换成float
float f4 = BitConverter.ToSingle(arrVal4, 0); // 26.5
- IQM区
// I区 I0.0
var val5 = plc.Read("I0.0"); // fale
// Q区 QW1
var val6 = plc.Read("QW1"); // 180
// M区 M0.3
var val7 = plc.Read("M0.3"); // true
方式二:Read(dataType,db,startaddr,count,bitaddr)
DB2.DBX0.0
按拉访问
var val9 = plc.Read(
DataType.DataBlock, // 读取的存储区 db块
2, // db的地址:db1即1,db2即2
0, // 读取的字节的开始位置,偏移量值
VarType.Bit, //读取单位:位
1, // 读取的数量
0 // 如果读取单位是按位读取,位的地址
); // true
I0.0
var val10 = plc.Read(
DataType.Input, // 读取的存储区 I区
0, // 对于I、Q、M区这里传0
0, // 读取的字节的开始位置,偏移量值
VarType.Bit, //读取单位:位
1, // 读取的数量
0 // 如果是按位读取,位的地址
); // false
QW1
var val11 = plc.Read(
DataType.Output, // 读取的存储区 Q区
0, // 对于I、Q、M区这里传0
1, // 读取的字节的开始位置,偏移量值
VarType.Word, //读取单位:字
1 // 读取的数量
); // 180
- 读取数组中的两个值
var val12 = plc.Read(DataType.DataBlock, 2, 8, VarType.DWord, 2); // {0, 88}
字符串读取:
字符串第一个字节存的是总字节数,第二个字节存的是字符串长度
- 读取:str1的总字节数和字符串长度
// 读取str1,str1在db区设置了默认值:study
// str1总字节数
var totalCount= plc.Read(DataType.DataBlock, 2, 16, VarType.Byte, 1); // 254
// str1字符串长度
var lengthCount = plc.Read(DataType.DataBlock, 2, 17, VarType.Byte, 1); // 5
int length = Convert.ToInt32(lengthCount); // 转int // 5
- 读取str1
string stateName = plc.Read(DataType.DataBlock, 2, 18, VarType.String, length).ToString(); // study
- 读取中文字符串str2
中文字符串,一个占两字节,不能用上面方式读取
// 字符串长度
var lengthCount1 = plc.Read(DataType.DataBlock, 2, 273, VarType.Byte, 1);
int length1 = Convert.ToInt32(lengthCount1);
// ReadBytes
byte[] byteArr = plc.ReadBytes(DataType.DataBlock, 2, 274, length1);
string str02 = Encoding.Default.GetString(byteArr); // 哈哈
方式三:按字节读取
从偏移量528开始获取13个字节
byte[] arrList = plc.ReadBytes(DataType.DataBlock, 2, 528, 13);
- count
// arrList01的值 [0] 0, [1] 100
byte[] arrList01 = arrList.Take(2).ToArray();
// 如果是数据放在字节数组后面的索引(有的操作系统这样,有的不一样)
if (BitConverter.IsLittleEndian)
// 翻转再转无符号16位整数 [0] 100, [1] 0
arrList01 = arrList01.Reverse().ToArray();
ushort count = BitConverter.ToUInt16(arrList01, 0); // 100
- rcount
// arrList02:[0] 0, [1] 200
byte[] arrList02 = arrList.Skip(2).Take(2).ToArray();
if (BitConverter.IsLittleEndian)
arrList02 = arrList02.Reverse().ToArray();
ushort rcount = BitConverter.ToUInt16(arrList02, 0); // 200
byte length = arrList[6];
byte[] arrlist03 = arrList.Skip(8).Take(length).ToArray();
string str02 = Encoding.Default.GetString(arrlist03);
- strstr
byte[] arrlist03 = arrList.Skip(6).Take(5).ToArray();
string str02 = Encoding.Default.GetString(arrlist03); // study
方式四:ReadClass
新建数据模型
public class PlcData {
// 属性顺序与db中的变量顺序一致
public ushort Count { get; set; }
public ushort RCount { get; set; }
}
ReadClass (model,db,startAddr)
PlcData data = new PlcData();
plc.ReadClass(data, 2, 524);
// 执行后:
// data.Count = 100,data.Count = 200
- 或者用:
ReadClass<model>(db,startAddr)
PlcData data1 = plc.ReadClass<PlcData>(2, 528);
// 执行后:
// data.Count = 100,data.Count = 200
写数据
方式一:字符串地址
Write("地址",value);
// 写bool值
plc.Write("DB2.DBX0.0", false);
plc.Write("I0.0", true);
// ushort
ushort val = 800;
plc.Write("DB2.DBW528", val);
// uint
plc.Write("DB2.DBD12", 50);
// float
float f1 = 28.5f;//浮点数
plc.Write("DB2.DBD2", f1);
如下图红框为修改后的值:
第二种:Write(DataType,db,startAddr,value,[bitAddr]);
// DB2.DBX0.0
plc.Write(DataType.DataBlock, 2, 0, true, 0);
// QW1
ushort uVal = 280;
plc.Write(DataType.Output, 0, 1, uVal);
第三种:Write(DataItem)、Write(DataItem[] )
// M0.3
DataItem di = new DataItem();
// M区
di.DataType = DataType.Memory;
di.DB = 0;
di.StartByteAdr = 0;
di.BitAdr = 3;
di.Value = false;
// DBD12
int iVal = 88;
DataItem di1 = new DataItem();
di1.DataType = DataType.DataBlock;
di1.DB = 2;
di1.StartByteAdr = 12;
di1.Value = iVal;
// 写入
plc.Write(di, di1);
1
1
1
1
1
1
1
1
1
1