一、西门子PLC系统构成
如下图就是一个组态完毕的西门子S7-300的模型:
根据标号,各个模块分别是:
1.电源模块(PS),供电专用
2.CPU模块(CPU),负责处理信息
3.通信模块(IM)
4.数字量输入模块(DI)
5.数字量输出模块(DO)
6.模拟量输入模块(AI)
7.模拟量输出模块(AO)
二、S7协议结构
S7Comm(S7Communication)是西门子专有的协议,是西门子S7通讯协议簇里的一种。
S7协议的TCP/IP实现依赖于面向块的ISO传输服务。S7协议被封装在TPKT和ISO-COTP协议中,这使得PDU(协议数据单元)能够通过TCP传送。它用于PLC编程,在PLC之间交换数据,从SCADA(监控和数据采集)系统访问PLC数据以及诊断目的。
S7Comm以太网协议基于OSI模型:
- 第1-4层会由计算机自己完成(底层驱动程序);
- 第5层TPKT,应用层数据传输协议,介于TCP和COTP协议之间。这是一个传输服务协议,主要用来在COTP和TCP之间建立桥梁;
- 第6层COTP,COTP是OSI7层协议定义的位于TCP之上的协议。COTP以“Packet”为基本单位来传输数据,这样接收方会得到与发送方具有相同边界的数据;
- 第7层,S7communication,这一层和用户数据相关,对PLC数据的读取报文在这里完成。
在具体的报文中,TPKT的作用是包含用户协议(5~7层)的数据长度(字节数);COTP的作用是定义了数据传输的基本单位(在S7Comm中PDUTYPE:DTdata)。
S7Comm协议OSI模型:
三、TPKT协议
通过TCP的传输服务。介于TCP和COTP之间。属于传输服务类的协议,功能为在COTP和TCP之间建立桥梁,其内容包含了上层协议数据包的长度。一般与COTP一起发送,当作Header段。
其中,TPKT的结构为:
Version:[1byte]版本信息。
Reserved:[1byte]保留(值为0x00)。
Length:[2bytes]TPKT、COTP、S7三层协议的总长度,也就是TCP的payload的长度。
从图中可知,其version=3,length=25(0x0019)。
四、COTP协议
COTP是OSI7层协议定义的位于TCP之上的协议。COTP以Packet
为基本单位来传输数据,这样接收方会得到与发送方具有相同边界的数据
。
COTP协议分为两种形态,分别是COTP连接包
(COTPConnectionPacket)和COTP功能包
(COTPFuctionPacket)。
4.1COTP连接包
COTP连接包(COTPConnectionPacket)也就是S7Comm的握手包,如下图所示:
其中,COTP连接包的头结构为:
0(Unsignedinteger,1byte):Length,COTP后续数据的长度(注意:长度不包含length的长度),一般为17bytes。
1(Unsignedinteger,1byte):PDUtyp,协议数据单元类型有:
0x01:EDExpeditedData,加急数据
0x02:EAExpeditedDataAcknowledgement,加急数据确认
0x04:UD,用户数据
0x05:RJReject,拒绝
0x06:AKDataAcknowledgement,数据确认
0x07:ERTPDUError,TPDU错误
0x08:DRDisconnectRequest,断开请求
0x0C:DCDisconnectConfirm,断开确认
0x0d:CCConnectConfirm,连接确认
0x0e:CRConnectRequest,连接请求
0x0f:DTData,数据传输
Destinationreference:2bytes,目标的引用,可以认为是用来唯一标识目标
Sourcereference:2bytes,源的引用,同上
opt:[1byte],其中包括Extendedformats(是否使用拓展样式)、Noexplicitflowcontrol(是否有明确的指定流控制),值都是Boolean类型。
Parameter:7~?(length-7bytes,一般为11bytes),参数。一般参数包含Parametercode
(1byte)、Parameterlength
(1byte)、Parameterdata
三部分。
i)SourceTSAP:源设备的TSAP(KEPSERVEROPC)
ii)DestinationTSAP:目的设备的TSAP(S7-200SMARTPLC)
TSAP这个概念还是不清楚,查到了:TSAP分为LocalTASP(相当于采集程序的地址)和RemoteTSAP(相当于PLC的地址)
连接请求包:
连接确认包:
4.2COTP功能包
结构如下:
COTP功能包的头结构为:
0(Unsignedinteger,1byte):Length,COTP后续数据的长度(注意:长度不包含length的长度),一般为2bytes。
1(Unsignedinteger,1byte):PDUtype,类型有:
0x01:EDExpeditedData,加急数据
0x02:EAExpeditedDataAcknowledgement,加急数据确认
0x04:UD,用户数据
0x05:RJReject,拒绝
0x06:AKDataAcknowledgement,数据确认
0x07:ERTPDUError,TPDU错误
0x08:DRDisconnectRequest,断开请求
0x0c:DCDisconnectConfirm,断开确认
0x0d:CCConnectConfirm,连接确认
0x0e:CRConnectRequest,连接请求
0x0f:DTData,数据传输
opt:[1byte],其中包括Extendedformats、Noexplicitflowcontrol,值都是Boolean类型。
五、S7Comm协议
S7Comm数据作为COTP数据包的有效载荷,第一个字节总是0x32作为协议标识符。
S7Comm协议包含三部分:
Header
Parameter
Data
5.1头(Header)
S7CommHeader的格式为:
ProtocolID:[1byte]协议常量,始终设置为0x32
MessageType:[1byte]消息的一般类型(有时称为ROSCTR类型),消息的其余部分在很大程度上取决于MessageType和功能代码。
0x01-JOB(Request:jobwithacknowledgement):作业请求。主站发送的请求(例如,读/写存储器,读/写块,启动/停止设备,设置通信);
0x02-ACK(acknowledgementwithoutadditionalfield):确认响应,没有数据的简单确认(未遇到过由S7300/400设备发送得);
0x03-ACK_DATA(Response:acknowledgementwithadditional
field):确认数据响应,这个一般都是响应JOB的请求;
0x07USERDATA:原始协议的扩展,参数字段包含请求/响应ID(用于编程/调试,读取SZL,安全功能,时间设置,循环读取…)。
RedundancyIdentification(Reserved):[2bytes]冗余数据,通常为0x0000;
ProtocolDataUnitReference:[2bytes],协议数据单元参考,通过请求事件增加;
Parameterlength:[2bytes],参数的总长度
Datalength:[2bytes],数据长度。如果读取PLC内部数据,此处为0x0000;对于其他功能,则为Data部分的数据长度;
其中最重要的字段就是ROSCTR,它决定了后续参数的结构.
在响应数据包中,还有可能存在错误信息。
其错误信息结构为:
10(unsignedinteger,1bytes):Errorclass,错误类型:可能错误的常量
11(unsignedinteger,1bytes):Errorcode,错误代码:可能错误的常量
5.2作业请求(Job)和确认数据响应(Ack_Data)
S7Comm中Job和Ack_Data中的Parameter项的第一个字段是function(功能码),其类型为Unsignedinteger,大小为1byte,决定了其余字段的结构、消息的目的。
所以接下来,将进一步介绍各功能码对应的结构和作用。
5.2.1建立通信(Setupcommunication[0xF0])
建立通信在每个会话开始时被发送,然后可以交换任何其他消息。它用于协商ACK队列的大小和最大PDU长度,双方声明它们的支持值。ACK队列的长度决定了可以同时启动而不需要确认的并行作业的数量。PDU和队列长度字段都是大端。
字段:
FunctionCode:功能代码,通信设置为0xf0
Reserverd:保留字段,默认为0x00
MaxAmQCaller:Ack队列的大小(主叫)
MaxAmQCallee:Ack队列的大小(被叫)
PDUlength:PDU长度。
JOB
Ack_Data
其协商结果为:ACK队列的大小为1;最大PDU长度为240。
5.2.2读取值(ReadVar[0x04])
数据读写操作通过指定变量的存储区域,地址(偏移量)及其大小或类型来执行。
5.2.2.1当PDU为JOB时
S7comm结构如下:
Parameter字段是Itemcount:
1、Variablespecification:确定项目结构的主要类型,通常为0x12,代表变量规范;
2、Lengthoffollowingaddressspecification:本Item其余部分的长度
3、SyntaxIdsofvariablespecification:确定寻址模式和其余项目结构的格式;
4、Transportsizesinitemdata:确定变量的类型和长度;
5、Requestdatalength:请求的数据长度
6、DBnumber,DB模块的编号,如果访问的不是DB区域,此处为0x0000;
7、Area:区域类型。
8、Address:地址。
图中item1是读取DB1的0x000010(DB1.DBX2.0BIT1)值,并且类型为BIT的请求。
5.2.2.2当PDU为Ack_Data时
S7comm结构如下:
其Parameter只有function、itemcount两个字段。
下面是Data
Returncode:1byte,返回代码;
Transportsize:1byte,数据的传输尺寸;
Length:2bytes,数据的长度;
Data:数据;
Fillbyte:填充字节。
上图的响应包如下:
item【1】是读取DB1的0x000010(DB1.DBX2.0BIT1)值,并且类型为BIT的响应,其响应的数据为01
5.2.3写入值(WriteVar[0x05])
S7comm的结构(写入值的作业请求):
由此,Data的结构为:
Returncode:返回代码,这里是未定义,所以为Reserved(0x00);Transportsize:确定变量的类型和长度:Length:2bytes,写入值的数据长度;Data:1byte,写入的值;Fillbyte:填充字节,如果数据的长度不足Length的话,则填充;
向地址为0x000008的Flags(M)写入0x00的作业请求
S7comm的结构(写入值的确认数据响应)
图中的item【1】,说明向地址为0x000008的Flags(M)写入0x00成功!
六、简单总结-S7协议工作流程
1、client与server通过socket建立连接,过程是标准的TCP连接方式,这一步完成连接的建立
2、client发送COTP,请求连接PLC,报文中包含CRConnectRequest和DestinationTSAP,从而标识出CPU的机架号和槽号
3、PLC返回COTP,确认连接,报文中包含CCConnectConfirm,此时server已经明确client与哪个CPU进行通讯
4、client发送S7Communication给server,报文中包含Setupcommunication,即通讯请求
5、server返回S7Communication给client,报文的ROSCTR为ACK_DATA,有确认的意思,包含了对作业请求的回复
6、client与server发送交换数据的报文,仍以S7Communication完成