物联网-S7Comm协议
- ■ 调试工具
- ■ S7协议-简介
- ■ S7协议和modbusTCP协议区别
- ■ OSI 层 S7 协议
- ■ S7协议数据结构 (TPKT+COTP+S7Comm)
- ■ TPKT(第五层:会话层) 总共占4个字节
- ■ COTP(第六层:表示层)
- ■ 1. COTP连接包(COTP Connection Packet)也就是S7Comm的握手包
- ■ 2. COTP功能包 (COTP Fuction Packet)
- ■ S7Comm(第七层:应用层)总用占24个字节
- ■ 1. S7Comm Header:
- ■ 2. S7Comm Parameter:
- ■ S7协议的工作流程
- ■ 数据包分析
- ■ S7 Setup Communication (Job)
- ■ S7 Setup Communication (ACk_data)
- ■ 读取数据 (Job)
- ■ 读取数据 (ACk_data)
- ■ 读取数据
- ■ 读写部分代码
■ 调试工具
Wireshark 抓包工具
Wireshark 抓包工具进行抓包看详细的发送报文格式。
西门子PLC调试助手
■ S7协议-简介
S7Comm( S7 Communication)是西门子专有的协议,是西门子 S7 通讯协议簇里的一种。
S7 通信协议是西门子 S7 系列 PLC 内部集成的一种通信协议,是 S7 系列 PLC 的精髓所在。
它是一种运行在传输层之上的(会话层/表示层/应用层)、经过特殊优化的通信协议,其信息传输可以基于 MPI 网络、 PROFIBUS 网络
或者以太网。
■ S7协议和modbusTCP协议区别
| 项目 | 说明 |
|---|---|
| 1 | 工作方式:S7协议是基于串行通信方式进行通信的, 而modbusTCP协议则采用了基于以太网的通信方式,可以实现更高的数据传输速度和数据量。 |
| 2 | 通信速度:S7通信速度相对较慢,一般为12Mbps以下; modbusTCP协议则支持更高的通信速度和更广的数据带宽,可达到100Mbps或以上的速度。 |
| 3 | 网络拓扑:S7协议在网络拓扑方面相对简单,通常采用星形网络拓扑; 而modbusTCP协议支持基于以太网的网状拓扑结构,可以实现更复杂的网络配置和更完备的自组网功能。 |
| 4 | 实时性:modbusTCP协议具有更高的实时性能,可满足工业自动化领域的实时控制要求。 |
■ OSI 层 S7 协议
| OSI层 | S7 协议 | – |
|---|---|---|
| 第 7 层: | 应用层 S7 协议 S7 Communication | |
| 第 6 层: | 表示层 S7 协议(COTP) | |
| 第 5 层: | 会话层 S7 协议(TPKT) | |
| 第 4 层: | 传输层 Transmission Control Protocol | |
| 第 3 层: | 网络层 IP | |
| 第 2 层: | 数据链路层 Ethernet | |
| 第 1 层: | 物理层 Ethernet |
■ S7协议数据结构 (TPKT+COTP+S7Comm)
■ TPKT(第五层:会话层) 总共占4个字节

| 版本号 | 预留 | 长度 |
|---|---|---|
| 1字节 | 1字节 | 2字节 |
| 0x03 | 0x00 | 0x001F |
■ COTP(第六层:表示层)
■ 1. COTP连接包(COTP Connection Packet)也就是S7Comm的握手包

| 长度 | PDU类型(DT Data) | 目标引用 DST Ref | SRC Ref | Opt | Parameters |
|---|---|---|---|---|---|
| 1字节 | 1字节 | 2 字节 | 2 字节 | 1字节 | N 字节 |
■ 2. COTP功能包 (COTP Fuction Packet)

| Length | PDU type | opt |
|---|---|---|
| 1字节 | 1字节 | 1字节 |
| 注意:长度不包含length的长度 | PDU类型 | Boolean类型 |
| PDU类型 | 介绍 |
|---|---|
| 0x1: | ED Expedited Data,加急数据 |
| 0x2: | EA Expedited Data Acknowledgement,加急数据确认 |
| 0x4: | UD,用户数据 |
| 0x5: | RJ Reject,拒绝 |
| 0x6: | AK Data Acknowledgement,数据确认 |
| 0x7: | ER TPDU Error,TPDU错误 |
| 0x8: | DR Disconnect Request,断开请求 |
| 0xC: | DC Disconnect Confirm,断开确认 |
| 0xD: | CC Connect Confirm,连接确认 |
| 0xE: | CR Connect Request,连接请求 |
| 0xF: | DT Data,数据传输 |
■ S7Comm(第七层:应用层)总用占24个字节
■ 1. S7Comm Header:

| 协议ID(Protocol ID) | PDU type | 预留 | PDU Reference | 参数长度 | 数据长度 | Error class | Error code |
|---|---|---|---|---|---|---|---|
| 1字节 | 1字节 | 2字节 | 2字节 | 2字节 | 2字节 | 1字节 | 1字节 |
| 编号 | 类型字节 | 说明 |
|---|---|---|
| 0 | (unsigned integer, 1 byte): | Protocol Id,协议ID,通常为0x32; |
| 1 | (unsigned integer, 1 byte): | ROSCTR,PDU type,PDU的类型 |
| 2~3 | (unsigned integer, 2 bytes): | Redundancy Identification (Reserved),冗余数据,通常为0x0000; |
| 4~5 | (unsigned integer, 2 bytes): | Protocol Data Unit Reference,it’s increased by request event。协议数据单元参考,通过请求事件增加; |
| 6~7 | (unsigned integer, 2 bytes): | Parameter length,the total length (bytes) of parameter part。参数的总长度; |
| 8~9 | (unsigned integer, 2 bytes): | Data length,数据长度。如果读取PLC内部数据,此处为0x0000;对于其他功能,则为Data部分的数据长度; |
| 10 | (unsigned integer, 1 bytes): | Error class,错误类型: |
| 11 | (unsigned integer, 1 bytes): | Error code,错误代码; |
■ 2. S7Comm Parameter:

功能码 Read Var:0x04
通信项数:0x01
(Item1)通信项1:
通信项 Header
变量指定: 0x12
地址长度: 0x0A
SyntaxID: 0x10
传输数据类型byte: 0x02
通信项 Param
读取长度: 0x04
DB号: 0x01
存储区类型DB存储区: 0x84
开始字节: 0x000000
| 编号 | 类型字节 | 说明 |
|---|---|---|
| 0 | (Unsigned integer, 1 byte): | Variable specification,确定项目结构的主要类型,通常为0x12,代表变量规范; |
| 1 | (Unsigned integer, 1 byte): | Length of following address specification,本Item其余部分的长度; |
| 2 | (Unsigned integer, 1 byte): | Syntax Ids of variable specification,确定寻址模式和其余项目结构的格式; |
| 3 | (Unsigned integer, 1 byte): | Transport sizes in item data,确定变量的类型和长度: |
| 4~5 | (Unsigned integer ,2 byte): | Request data length,请求的数据长度; |
| 6~7 | (Unsigned integer, 2 byte): | DB number,DB模块的编号,如果访问的不是DB区域,此处为0x0000; |
| 8 | (Unsigned integer, 1 byte): | Area,区域类型: |
| 9~11 | (Unsigned integer, 3 byte): | Address,地址。 |
■ S7协议的工作流程
| 工作流程 | 说明 |
|---|---|
| 1 | client与server 通过socket和标准的TCP的方式建立连接 |
| 2 | client发送COTP,请求连接PLC,报文中包含Source TSAP和Destination TSAP,从而标识出CPU的机架号和槽号 |
| 3 | PLC返回COTP,确认连接,报文中包含Source TSAP和Destination TSAP,此时server确定client与哪个CPU进行通讯 |
| 4 | client发送S7 Communication给server,报文中包含Setup communication,即通讯请求,包含PDU的长度 |
| 5 | server返回S7 Communication给client,报文的ROSCTR为ACK_DATA,有确认的意思,包含PDU的长度 |
| 6 | client与server发送交换数据的报文,仍以S7 Communication完成 |
2与3完成数据传输前连接的功能,
4与5则完成连接之后的通讯请求,如果绕过通讯请求的建立,在有TCP时就进行数据交换,服务器一般会直接断连。
- 建立Socket连接:进行TCP三次握手
- COTP的握手请求(请求建立通信)
- 整个S7的握手请求(请求建立操作通信)
- 进行读写操作(S7协议报文)
■ 数据包分析
■ S7 Setup Communication (Job)
■ S7 Setup Communication (ACk_data)

■ 读取数据 (Job)

■ 读取数据 (ACk_data)


0x123 == data 0x007b
■ 读取数据




■ 读写部分代码
using System;
using System.Net.Sockets;
namespace Zhaoxi.SiemensS7.Study
{
class Program
{
/// <summary>
/// VS2019 16.9 社区版
/// 框架.NET5 -> 项目没法直接找开
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// 调库
S7.Net.Plc plc = new S7.Net.Plc(S7.Net.CpuType.S71500, "192.168.151.200", 0, 1);
plc.Open();
VW100 Word short ishort int16 uint16
DB1.DBW100.0-7 Bit
S7.NET 粘包:两个报文一次接收了
请求了一个Word,2个Byte
//var value = plc.Read("DB2.DBW0");
基本的读写 读SZL、启停、上传下载
// 关于连接报文:
// 假如保证通信环境不会掉线,只做一次
// 断线重连,再次进行TCP三次握手 COTP Setup
// 连接部分封装一个方法,这个方法主要做检查连接状态,Connect的重连操作-》连接正常了 再做COTP Setup建立连接
// 第一种,在一个后台线程做连续的连接状态判断,
// 第二种,在读写操作方法里调用这个方法
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 可以进行TCP通信 ,也可以进行UDP通信
// 1、进行TCP的三次握手 连接西门子PLC 默认102端口
socket.Connect("192.168.151.200", 102);
try
{
// 2、进行COTP的连接请求
byte[] cotpBytes = new byte[] {
// TPKT
0x03,0x00,0x00,0x16,
// COTP
0x11,
0xe0,// 连接请求
0x00,0x00,0x00,0x00,0x00,
// Parameter-code
0xc1,0x02,0x10,0x00,
0xc2,0x02,0x03,0xFF,// 机架号和插槽号进行特殊的计算 机架0,插槽1
0xc0,0x01,0x0a
};
socket.Send(cotpBytes);
int count = socket.Receive(new byte[22]);
}
catch (Exception ex)
{
}
// S7 Setup Communication // 还有进行数据交换 PDU
byte[] setupBytes = new byte[] {
// TPKT
0x03,0x00,0x00,0x19,
// COTP
0x02,
0xf0,// 数据传输
0x80,
// S7-Header
0x32,
0x01,
0x00,0x00,0x00,0x00,
// Parameter len
0x00,0x08,
// Data len
0x00,0x00,
// S7-Parameter
0xf0,// 读:0x04 写:0x05
0x00,
0x00,0x03,
0x00,0x03,
0x03,0xc0
};
socket.Send(setupBytes);
// 百度网盘下载地址,包括模拟器,博途、安装视频
// 已经建立好了通信,下一步进行数据的读写 DB I Q M
// 读写的报文与响应解析,明天继续
// V 区为什么读取不了?一会答疑的时候来讲
// 做读写操作 发送特定指令 启停
// 读哪个
// DB2.DBW10-
// 请求的是一个Word Bit 5 DBW10.5
// BIT BitAddr 可以是0-7任意数
// Byte Word DWord BitAddr只是0
int byteAddr = 10;
int bitAddr = 0;//
byteAddr = byteAddr << 3;
byteAddr += bitAddr;
byte[] readBytes = new byte[] { //31+12 43 2B
// TPKT
0x03,0x00,0x00,0x2b,
// COTP
0x02,
0xf0,// 数据传输
0x80,
// S7-Header
0x32,
0x01,
0x00,0x00,0x00,0x00,
// Parameter-Len
0x00,0x1a, //26个字节长度
// Data-Len
0x00,0x00,
// S7-Paramter 26个字节
0x04,// Read Var
0x02,// 1个ITEM 涉及多读(不同存储区,分散存储的数据)
// S7-Parameter-Item-1
0x12,0x0a,
0x10,
0x04,// 请求一个Word类型 0x02 Byte
0x00,0x01,// 读取长度
0x00,0x02,//DB块的编号
0x84,// 区域类型
// 把这个地址分成3个字节
(byte)(byteAddr/256/256%256),
(byte)(byteAddr/256%256),
(byte)(byteAddr%256),
// S7-Parameter-Item-2 读I2.1 12个字节
0x12,0x0a,
0x10,
0x01,// 请求一个Word类型 0x02 Byte
0x00,0x02,// 读取长度 ,读Bit 只能1个
0x00,0x00,//DB块的编号
0x81,// 区域类型
// 把这个地址分成3个字节
(byte)(((2<<3)+1)/256/256%256),
(byte)(((2<<3)+1)/256%256),
(byte)(((2<<3)+1)%256)
// 肯定没有,固定的几个长度信息没有改
};
socket.Send(readBytes);
// 写
// 下去
}
}
}


















