尹大宇
摘 要 介绍了PC与西门子S7-300PLC在.Net平台下用TCP/IP协议实现通讯的方法。
【关键词】S7-300 PLC TCP/IP套接字 .Net
随着Internet/ Intranet的发展,以太网已渗透到各个角落,今天的控制系统和工厂自动化系统,以太网的应用几乎已经和PLC一样普及。以太网相对于其他通讯方式(如Profibus/Mpi)有许多优势:
(1)速度更快。西门子CP 1543-1的通讯带宽已经可达1000Mbps。
(2)诊断更加方便快捷。简单的ping操作就可以诊断大部分通讯问题。
(3)成本低。不再需要使用特殊的适配器来连接到PLC,只需普通的网线。
因此,本文的研究将基于以太网的TCP/IP协议进行讨论。
1 .NET平台简介
.NET Framework的核心是其运行库的执行环境,称为公共语言运行库(CLR)或.NET运行库。在CLR执行编写好的源代码之前,需要编译它们(在C#中或其他语言中)。在.NET中,编译分为两个阶段:
(1)把源代码编译为Microsoft中间语言(IL)。
(2)CLR把IL编译为平台专用的代码。
这个两阶段的编译过程非常重要,因为Microsoft中间语言(托管代码)是提供.NET的许多优点的关键。
Microsoft中间语言与Java字节代码共享一种理念:它们都是低级语言,语法很简单(使用数字代码,而不是文本代碼),可以快速地转换为内部机器码。对于代码来说,这种精心设计的通用语法有很重要的优点:平台无关性、提高性能和语言的互操作性。因此,基于.NET平台开发的应用程序具有更好的移植性,也是跨平台应用程序开发的很好选择。
2 PLC与PC的TCP/IP通讯协议
基于以太网TCP/IP协议有两种通讯方式:面向对象的通讯协议(TCP)和面向无连接的通讯协议(UDP)。TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。为了提高数据的有效性,本文使用该通讯方式。
西门子通讯协议是西门子PLC通讯的基础,它按照确定的方式来进行定义,然后将定义完成的报文依赖于TCP协议来进行传输。每一条通讯报文都包含着一条指令(例如读取、写入)或者明确的回复。协议的封装如图1所示。
西门子通讯协议被封装在S7 PDU中,一条标准的通讯报文由几个基本的部分组成(本文以读取DB存储区(DB300.DBW29)变量的请求为例进行说明):
2.1 数据头
声明请求目的为读取(0x32 0x01)。数据流(16进制)如表1所示。
2.2 参数定义
声明请求为读取(0x04),变量个数(0x01代表只读取一个变量),标准头(0x12 0x0a 0x10),变量的类型(0x02代表Byte),长度(“0x00 0x02”长度为2字节),对象(0x84代表DB存储区),地址(“0x01 0x2c”代表DB300,“0x00 0x00 0xe8”代表地址偏移位29,在这里是DBW29)。数据流(16进制)如表2所示。
3 PC与PLC通讯方法的实现
3.1 本文的研究内容是基于下图硬件基础来实现的
它包括一个CPU317-2DP,一个CP343-1通讯模块等,已组态CP343-1的IP地址为172.20.100.10,硬件组态如图2所示。用于编程实现通讯的PC机为带以太网口的普通笔记本电脑,IP地址为172.20.100.222,测试读取的变量为DB300.DBW29。
3.2 通讯的主要过程
整个通讯程序在Visual Studio 2015开发平台下用C#语言实现,通讯的主要过程包括如下几个步骤。
(1)建立一个套接字连接到PLC。注意程序必须包含System.Net.Sockets名称空间。部分代码如下:
int result;/*定义返回值*/bool temp = false; //定义状态变量
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个套接字
(2)连接套接字:
if (sock.Connected==true)//连接前判断是否为重复连接
{result = 1;//是则返回值1,已经建立连接 }else{try
{sock.Connect(host, port);//连接套接字
//这里host为CP的IP地址“172.20.100.10”,port为整数102(默认)
temp = true;/*代表已经连接上*/result = 1;}
catch (SocketException e)//连接错误则输出报警信息{errorStr = e.Message + " . Error code:" + e.ErrorCode;result = 0;temp = false;}
(3)与PLC建立握手连接:
if (temp == true)//如果套接字连接正常,则进行握手连接
{try{isSize8 = FControlPDUDC.IniTSAP(rack, slot, ConnectionType);
IniPDU();/*连接请求PDU初始化*/ byte[] byteRecv = new byte[240];
byte[] PDUmsg = StructToBytes(FControlPDUDC);
/*初始化完成后,PDUmsg[]字节数组为:
[0x03 0x00 0x00 0x16 0x11 0xe0 0x00 0x00 0x00 0x01 0x00 0xc0 0x01 0x0a 0xc1 0x02 0x01 0x00 0xc2 0x02 0x01 0x02]*/
int bytesSent = sock.Send(PDUmsg);int bytesRec = sock.Receive(byteRecv);byte[] byteRecv = new byte[240];
……//初始化NegMsg
/*初始化完成后用于再次握手的NegMsg[]字节数组为:
[0x03 0x00 0x000x190x02 0xf0 0x80 0x32 0x01 0x00 0x00 0x03 0x00 0x00 0x08 0x00 0x00 0xF0 0x00 0x00 0x01 0x00 0x01 0x01 0xe0]*/
int NegSent = sock.Send(NegMsg);int NegbytesRec = sock.Receive(NegbyteRecv);result = 1;}catch (SocketException e)
{result = 0;errorStr = e.Message + ". Error code:" + e.ErrorCode;}}
(4)讀取DB存储区变量测试:
int result = 0;if (sock.Connected==true)
{…… /准备读取变量PDU,初始化 PDUSend
/*初始化完成后,PDUSend[]字节数组为:
[0x03 0x00 0x00 0x1f 0x02 0xf0 0x80 0x32 0x01 0x00 0x00 0x04 0x00 0x00 0xe0 0x00 0x00 0x04 0x01 0x12 0x0a 0x10 0x02 0x00 0x0a 0x01 0x2c 0x84 0x00 0x00 0xe8]*/
try{int i = sock.Send(PDUSend);sock.Receive(DataRecv);
receiveBuffer = new byte[totalNum];
……/*处理PLC返回的字节*/
result = 1;}catch (SocketException e)//异常处理
{errorStr = e.Message + ". Error code:" + e.ErrorCode;result = 0;}}
else{result = 0;}return result;
4 结论
随着微软宣布将全部.NET服务器端框架开源,将.NET运行平台扩展至Linux和Mac OS,让开发者能够使用.NET在Windows、Mac和Linux三大平台上开发应用。基于.NET平台的开发的通讯程序几乎不需要修改任何代码就可以很好的移植到任何支持.NET的平台之上。因此,本文的研究对于跨平台西门子S7_300PLC通讯的开发也具有指导意义。
参考文献
[1]Nagel C,Evjen B,Glynn J,et al. Professional C# 4.0 and.NET 4[J]. Wiley John + Sons,2010.
[2]贾涛.西门子S7-200以太网通讯协议研究[J].电子技术与软件工程,2014(24):30-32.