S7Comm通信库是C#封装的以太网连接西门子S7-200,S7-200SMART,S7-300,S7-400,S7-1200,S7-1500 PLC以及LOGO!0BA7/0BA8 / 8.FS4的驱动程序
1连接
(NuGet程序包 --> S7Comm) S7Comm通信库提供4个重载的连接方法,LOGO!0BA7/0BA8/8.FS4/CP243-1以太网模块使用S7Comm.Tsap()参数重载的方法,透传方式连接请使用带端口号参数重载的方法;
TSAP是"Transport Services Access Point "传输服务访问点它是传输层与会话层之间的访问接口,每一个TSAP可以唯一标识一个访问实例;TSAP:01->PG;02->OP;03至0x10->S7Basic
一对传输服务访问点(S7-200SMART/S7-300/S7-400/S7-1200/S7-1500缺省值本地传输服务访问点高字节localTsapHi =0x01,本地传输服务访问点低字节localTsapLo=0x00,远程传输服务访问点高字节RemoteTsapHi=0x03,远程传输服务访问点低字节RemoteTsapLo=0x20 * rack + slot,S7-200SMART/S7-1200/S7-1500缺省值rack = 0,slot = 1,S7-300/S7-400缺省值rack = 0,slot = 2 或见硬件组态;LOGO!0BA7/0BA8/8.FS4或CP243-1以太网模块见硬件组态)
Rack和Slot不同类型的PLC其Rack和Slot的定义不同,详见下面的列表:
PLC类型 Rack Slot 备注
S7-300 0 2
S7-400 不确定 不确定 见硬件组态
S7-1200/1500 0 1 0或1
S7-200SMART 0 1
S7-1200/1500系列PLC采用扩展的S7协议
CPU的访问级别必须为"完全访问权限",CPU的"连接机制"中要勾选"允许来自远程对象的PUT/GET通信访问",对数据块的访问仅限于全局数据块(Global DB),并且需要取消勾选"优化的块访问
以下是建立连接的使用方法
if (!siemensS7.Connect("192.168.100.60", 0, 1))return;
if (!siemensS7.Connect("192.168.100.60",102, 0, 1))return;
if (!siemensS7.Connect("192.168.100.60", new S7Comm.TsapPair(new S7Comm.Tsap(0x01, 0x00), new S7Comm.Tsap(0x03, 0x20*0+1))))return;
2 读变量操作ReadVar
1:读取DB2 8开始的2个字节(DB2.DBW8)(该方法已做分包处理读取字节数不受PDU-18字节的限制 S7协议单次报文读取最大PDU-18 942个字节数)
byte[] requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock,2, 8, 2);
2:读取DB2.DBB1228开始的1024个字节
byte[] requst =siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 1228, 1024);//字节1228开始的第0个位
byte[] requst= siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 0, 1024,9824);//字节0开始的第9824个位
byte[] requst= siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 106, 1024,8976);//字节106开始的8976个位
3:读取DB2.DBW1100开始连续的3个int(C# Short)类型的数据
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 1100, 3, S7Comm.DataType.Short, 0);//字节1100开始第0个位
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 0, 3, S7Comm.DataType.Short, 8800);// 字节0开始第8800个位
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 30, 3, S7Comm.DataType.Short, 8560);// 字节30开始第8560个位
4:读取DB2.DBX96.2开始的连续的5个位
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 96, 5, S7Comm.DataType.Bit,2);//字节96开始的第0个位
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 0, 5, S7Comm.DataType.Bit,770);//字节0开始的第770个位
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 24, 5, S7Comm.DataType.Bit, 578);//字节24开始的第578个位
5:读取DB2.DBB108开始连续4个字符串
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 108, 4, S7Comm. DataType.String, 0);
6:读取DB2.DBD10 32位浮点数
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 10, 1, S7Comm. DataType.Float, 0);
7:读取MW100的值(字符串地址可以忽略大小写)
var requst = siemensS7.ReadVar("mw100", S7Comm. DataType.Short);
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.Marker, 0, 100, 1, S7Comm. DataType.Short, 0);
8:读取DB2.DBBD20 32位有符号整数
int requst = siemensS7.ReadVar<int>("DB2.DBD20",S7Comm.DataType.Int);
9:读取DB2.DBX96.2 DB2.DBX96.3 DB2.DBX96.4
bool[]requst=siemensS7.ReadVar<bool[]>(S7Comm.MemoryArea.DataBlock, 2, 96, 3, S7Comm. DataType.Bit,2);
10:读DB2.DBW2676 16位宽字符
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 2676, 6, S7Comm. DataType.Wchar, 0);
string[] requst = siemensS7.ReadVar <string[]> (S7Comm.MemoryArea.DataBlock, 2, 2676, 6, S7Comm. DataType.Wchar, 0);
var requst = siemensS7.ReadVar("DB2.DBW2676", S7Comm.DataType.Wchar);
string requst = siemensS7.ReadVar <string> ("DB2.DBW2676", S7Comm. DataType.Wchar);
11: 读取P#DB2.DBX2300.0 64位Lint的值
var requsRt = siemensS7.ReadVar("P#DB2.DBX2300.0", S7Comm.DataType.Long);
12:读取P#DB2.DBX2308.0 64位Lint的值
var requst = siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 2308, 1, S7Comm.DataType.Long, 0);
13:多ITEM读取(多个存储区多个变量值)
List<S7Comm.SiemensItemVar> siemensItemVar = new List<S7Comm.SiemensItemVar>
{
new S7Comm.SiemensItemVar("DB2.DBX96.0",S7Comm. DataType.Bit),
new S7Comm.SiemensItemVar("DB2.DBX96.1",S7Comm. DataType.Bit),
new S7Comm.SiemensItemVar("DB2.DBX96.2",S7Comm. DataType.Bit),
new S7Comm.SiemensItemVar("DB2.DBX96.5",S7Comm. DataType.Bit),
new S7Comm.SiemensItemVar("DB2.DBB40", S7Comm. DataType.Byte),
new S7Comm.SiemensItemVar("DB2.DBD0",S7Comm.VarType.Float),
new S7Comm.SiemensItemVar("DB2.DBW6",S7Comm. DataType.Short),
new S7Comm.SiemensItemVar("DB2.DBB1098", S7Comm. DataType.Byte),
new S7Comm.SiemensItemVar("DB2.DBW1100", S7Comm. DataType.Short),
new S7Comm.SiemensItemVar("DB2.DBB108",S7Comm.DataType.String),
new S7Comm.SiemensItemVar("DB2.DBB172",S7Comm.DataType.String),
new S7Comm.SiemensItemVar("DB2.DBW236",S7Comm.DataType.Wstring),
new S7Comm.SiemensItemVar("DB2.DBW318",S7Comm.DataType.Wstring),
new S7Comm.SiemensItemVar("DB2.DBB2673",S7Comm.DataType.Char),
new S7Comm.SiemensItemVar("DB2.DBW2676",S7Comm.DataType.Wchar),
new S7Comm.SiemensItemVar("P#DB2.DBX2268.0",S7Comm. DataType.Double),
new S7Comm.SiemensItemVar("P#DB2.DBX2300.0",S7Comm. DataType.Long),
};
var requst = siemensS7.ReadVar(siemensItemVar);
14:多ITEM读取(多个存储区多个字节)
读取DB2.DBB40 DB2.DBB106 DB2.DBW1100 DB2.DBD0
List<S7Comm.SiemensItemGroup> siemensItemGroup = new List<S7Comm.SiemensItemGroup>
{
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,40,1),//40开始第0个位
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,104,1,16),//104开始的第16个位
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,1100,2),
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,0,4),
};
var requst = siemensS7.ReadVar(siemensItemGroup);
3 写变量操作WriteVar
1: DB2.DBD58以字节数组写入23.6
bool requst= siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock,2,58,new byte[] {66,98,204,205 });
bool requst=siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 58, BitConverter.GetBytes(Convert.ToSingle(23.6)).Reverse().ToArray());
//字节58开始的第0个位
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 0, Convert.ToSingle(23.6 ),464);//字节0开始的第464个位
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 42, BitConverter.GetBytes( Convert.ToSingle(23.6 )).Reverse().ToArray(),128); //字节42开始的第128个位
2: DB2.DBX86.2写入true
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 86, true,2);//字节86开始的第2个位
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 58, true,226); //字节58开始的第226个位
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 0,"true",S7Comm.DataType.Bit,690); //字节0开始的第690个位
3: DB2.DBB2674写入Q字符
bool requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 2674, "Q", S7Comm.DataType.Char,0);
4: DB2.DBB1102写入66
bool requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock, 2, 1102,Convert.ToInt16(66),0);
5: Lint64位整型 P#DB2.DBX2300.0写入5566
var requst = siemensS7.WriteVar(S7Comm.MemoryArea.DataBlock,2,2300,"5566",S7Comm. DataType.Long,0);
6: Lint64位整型 P#DB2.DBX2308.0写入6677
var requst = siemensS7.WriteVar("P#DB2.DBX2308.0",Convert.ToInt64(6677));
7: Lint64位整型 P#DB2.DBX2316.0写入5678
var requst = siemensS7.WriteVar("P#DB2.DBX2300.0",S7Comm.DataType.Long,"5678");
8: DB2.DBBD0写入33.66
var requst = siemensS7.WriteVar("DB2.DBD0", S7Comm. DataType.Float, "33.66");
9: DB2.DBB108写入字符串
var requst = siemensS7.WriteVar("DB2.DBB108", S7Comm. DataType.String, "写入字符串");
10: DB2.DBB120写入字符串
var requst = siemensS7.WriteVar("DB2.DBB120", "写入中文字符串");
11: DB2.DBX96.3写入TRUE
var requst = siemensS7.WriteVar("DB2.DBX96.3", true);
12:多ITEM写入(多个存储区多个变量值)
List<S7Comm.SiemensItemVar> siemensItemVar = new List<S7Comm.SiemensItemVar>
{
new S7Comm.SiemensItemVar("DB2.DBX96.0",S7Comm. DataType.Bit,true),
new S7Comm.SiemensItemVar("DB2.DBX96.3",S7Comm. DataType.Bit,true),
new S7Comm.SiemensItemVar("DB2.DBX96.7",S7Comm. DataType.Bit, "true"),
new S7Comm.SiemensItemVar("DB2.DBB40", S7Comm. DataType.Byte,88),
new S7Comm.SiemensItemVar("DB2.DBD0",S7Comm.VarType.Float,56.5566),
new S7Comm.SiemensItemVar("DB2.DBW6",S7Comm. DataType.Short,5),
new S7Comm.SiemensItemVar("DB2.DBB1098", S7Comm. DataType.Byte,7),
new S7Comm.SiemensItemVar("DB2.DBW1100",S7Comm. DataType.Short,6),
new S7Comm.SiemensItemVar("DB2.DBB108",S7Comm.DataType.String,"字符串"),
new S7Comm.SiemensItemVar("DB2.DBB172",S7Comm.DataType.String,"西门子字符"),
new S7Comm.SiemensItemVar("DB2.DBW236",S7Comm.DataType.Wstring,"宽字符"),
new S7Comm.SiemensItemVar("DB2.DBB2673",S7Comm.DataType.Char,'R'),
new S7Comm.SiemensItemVar("DB2.DBW2676",S7Comm.DataType.Wchar,'X'),
new S7Comm.SiemensItemVar("P#DB2.DBX2268.0",S7Comm. DataType.Double,56.78),
new S7Comm.SiemensItemVar("P#DB2.DBX2308.0",S7Comm. DataType.Long,8899),
};
var requst = siemensS7.WriteVar(siemensItemVar);
13:多ITEM写入(多个存储区多个字节)
DB2.DBD0写入32位浮点数 55.66 DB2.DBB40写入11 DB2.DBW80写入23 DB2.DBW1100写入56
List<S7Comm.SiemensItemGroup> siemensItemGroup = new List<S7Comm.SiemensItemGroup>
{
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,0,BitConverter.GetBytes(Convert.ToSingle(55.66)).Reverse().ToArray()),
new S7Comm. SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,40,new byte[]{11}),
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,50,BitConverter.GetBytes(Convert.ToInt16(23)).Reverse().ToArray(),240), //字节0开始的第240个位
new S7Comm.SiemensItemGroup( S7Comm.MemoryArea.DataBlock,2,1100,BitConverter.GetBytes(Convert.ToInt16(56)).Reverse().ToArray()),
};
var requst = siemensS7.WriteVar(siemensItemGroup);
4备注
S7协议的特点地址支持位寻址,如DB2.DBB106字节地址从106开始第0个位,字节地址0开始第848个位,字节地址100开始第48个位, DB2.DBX96.3字节地址从96开始第3个位,字节地址从0开始第771个位,字节地址从80开始第131个位
读取写入报文如下
siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 0,1,312);//字节地址0开始第312个位 读取DB2.DBB39
siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 20,1,152);//字节地址20开始第152个位 读取DB2.DBB39
siemensS7.ReadVar(S7Comm.MemoryArea.DataBlock, 2, 39,1);//字节地址39开始第0个位 读取DB2.DBB39
在sharp7中的位地址读取跟写入也有体现如Sharp7.S7Client s7Client = new Sharp7.S7Client();
int isConnect= s7Client.ConnectTo("192.168.100.60", 0,1);
if (isConnect==0)
{
byte[] buffer = new byte[1];
//769=96*8+1
s7Client.ReadArea(Sharp7.S7Area.DB,2,769,1,Sharp7.S7WordLength.Bit,buffer);//读取DB2.DBX96.1的值 //从0开始的第769个位
}
位地址=(写入或者读取的字节地址-startByteAddress起始字节地址)*8+写入或者读取的位地址 如 DB2.DBX96.3 (96-80)*8+3
支持对位的读写操作因此不需要读取对应的字节地址解析得到对应的值、多ITEM读写(同时读取或者写入多个不同的存储区);多组读取与写入对于多个不同存储区较为零散的变量,可以提高通信效率。此外S7协议一次性读取的字节数受PDU的限制,最大值是PDU减去18根据不同的CPU有240 480 960,PDU的值在建立S7连接第2次握手验证返回的报文的最后两个字节。
S7Comm读写变量方法基于线程安全并实时监测与服务器是否断线,当断线时触发委托执行重连机制,字符串地址varAddress参数格式需遵循 SiemensPLC绝对地址格式标准 DBx.DBBx DBx.DBWx DBx.DBDx DBx.DBXx.x MBx MWx MDx Mx.x IBx IWx IDx Ix.x QBx QWx QDx Qx.x 64位数据类型表示方法 P#DBx.DBXx.x P#Mx.x (P#M500.0 表示M500.0 Lint数据类型 P#DB2.DBX42.0 表示DB2 偏移地址42 数据类型为Lint)VBx VWx VDx V区也是DB1( VB0——> DB1.DBB0)
S7Comm枚举DataType是C#的数据类型(Wchar 宽字符 ,Wstring宽字符),使用时需根据PLC的数据类型进行等效的转换选择否则解析的数据不正确或者null,泛型写入方法通过反射得到写入数据的类型所以不支持宽字符,宽字符串写入,
如下表所示
C# VarType SiemensPLC
Bit 布尔 Bool
Byte, 8位有符号整数 Byte
Short 16位有符号整数 Int Word(0-65535)十进制
UsShort 16位无符号整数 Uint Word(-32768_32767)十进制
Int 32位有符号整数 Dint Dword(-2147483648_ 2147483647)十进制
Uint 32位无符号整数 Udint Dword(0-4294967295)十进制
Float 32位单精度浮点数 Real
Double 64位双精度浮点数 Lreal
Long 64位有符号整数
Lint Lword(-9223372036854775808_ 9223372036854775807)十进制
Ulong 64位无符号整数 Ulint Lword(0-18446744073709551615)十进制
Char 字符 Char
Wchar 宽字符 Wchar
String 字符串 String
Wstring 宽字符串 Wstring
QQ群:827757592
4 附录