1、S7协议通讯流程回顾
1)建立Socket连接:进行TCP三次握手
这里是指要建立socket的tcp连接,是tcp连接而不是udp连接,tcp连接是可靠连接,tcp连接就是要有稳定的IP地址,它是通过字节方式进行通讯,在程序中就是要创建socket对象,利用socket的方式来实现字节的发送和接收,包括解析数据,这个socket是连接谁呢?肯定是连接plc设备,所以plc设备必须有IP地址,端口号,那么谁去连接了,当然是我们的PC电脑,电脑在这个场景下就是我们的上位机,软件工程师通过开发应用程序来与PLC通讯,模型如下:
2)COTP的握手请求(请求建立通信)
在“握手”之后,并不能马上进行数据交换,需要进行这一步的操作,即客户端发送COTP报文给服务端,在COTP报文中包含“连接请求”和“Destination TSAP”,以明确CPU的机架号和槽号;服务端应答COTP报文,包含“连接确认”;这样服务端就清楚了客户端需要和哪个CPU来进行数据通讯。在这个过程中,有非常标准和严重要求的报文格式,这个过程会有22个字节,每个报文的字段内容代表不同的含义,千万不能搞错,否则服务器,也就是PLC就会不搭理你。报文信息如下,搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。
3)S7COMM的握手请求(请求建立操作通信)
在成功完成上面的COTP请求后,现在客户端发送S7 Communicaton报文给服务端,在S7Communicaton报文中包含“通讯请求”; 服务端反馈S7 Communicaton报文。同样的报文中每个字段都有含义,必须严格遵守,这个过程是交换通信信息,共25个字节,报文信息如下:搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。
4) 进行读写操作(S7协议报文)
在成功完成上面的1,2,3的三个过程后,现在才是读、写、PLC启停、时间、上传下载等,读取的报文比写入的报文要简单些,但报文结构确实复杂,需要大师给你开光,现在搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。
2、开搞socket连接
1)安装西门子博途v15环境
应用环境要求是win10企业版,搭建这个西门子PLC的环境还是蛮消耗时间,精力和能力,耐心的,要求也高,这个事情必须做好,不能偷懒,绝不能失败,否则整个系列的内容就实现不了,具体安装过程请看下面文章,这里不展示,因为过程实在是众多,需要细致。
windows10企业版安装西门子博途V15---01准备环境_博途v15.1安装需求-CSDN博客
windows10企业版安装西门子博途V15---02安装软件_博图v15软件安装步骤-CSDN博客
windows10企业版安装西门子博途V15---03安装仿真软件_西门子v15仿真软件-CSDN博客
windows10企业版安装西门子博途V15---04连接测试_博图v15第一次连接plc步骤-CSDN博客
1)西门子PLC存储区简介
I:数字量输入(DI)
Q:数字量输出
AI:模拟量输入
AQ:模拟量输出
V:变量存储区
M:位存储区
T:定时器存储区
C:计数器存储区
HC:高速计数器
AC:累加器
SM:特殊存储器
L:局部存储区
S:顺序控制继电器
DB:数据块
2)访问规则:bit、B、W、D B:byte W:word ->2byte D:double->4byte Bit: I0.0
DataType:
0x01 - BIT:一个无符号的bit
0x02 - BYTE:一个8位的数字
0x03 - CHAR:一个字符
0x04 - WORD:两个字节宽的无符号整数
0x05 - INT:两个字节宽的有符号整数。
0x06 - DWORD:四字节宽的无符号整数
0x07 - DINT:四字节宽的有符号整数
0x08 - REAL:四个字节宽的IEEE浮点数
0x1c - COUNTER:PLC程序计数器使用的计数器类型
示例:变量的示例地址是DB123X 2.1,它访问DB块123的第3个Byte的第2个Bit。
3)在本应用中,创建了一个192.168.1.66的PLC设备和hnplc项目,如图
2)创建vs项目
3、连接代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace west.siemenscomm
{
internal class Program
{
/// <summary>
/// plc的ip地址
/// </summary>
static string _ip="192.168.1.66";
/// <summary>
/// 端口号
/// </summary>
static int _port=102;
/// <summary>
/// 机柜号,插槽号
/// </summary>
static byte _rack=0, _slot=1;
/// <summary>
/// socket对象
/// </summary>
static Socket socket = null;
/// <summary>
/// 时间事件
/// </summary>
static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
/// <summary>
/// 连接状态
/// </summary>
static bool connectState = false;
static void Main(string[] args)
{
Connect();
Console.ReadKey();
}
private static void Connect(int timeout = 50)
{
TimeoutObject.Reset();
try
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect(_ip, _port, callback =>
{
connectState = false;
var cbSocket = callback.AsyncState as Socket;
if (cbSocket != null)
{
connectState = cbSocket.Connected;
if (cbSocket.Connected)
cbSocket.EndConnect(callback);
}
TimeoutObject.Set();
}, socket);
TimeoutObject.WaitOne(2000, false);
}
catch (SocketException ex)
{
if (ex.ErrorCode == 10060)
Console.WriteLine(ex.Message);
}
if (socket == null || !socket.Connected || ((socket.Poll(200, SelectMode.SelectRead) && (socket.Available == 0))))
{
Console.WriteLine("网络连接失败");
}
Console.WriteLine(connectState==true?"连接成功":"连接失败");
}
}
}
一定注意一个问题,看这里
4)运行测试
3、小结
这就是第一个流程,建立TCP的三次握手,它是通过socket对象通讯实现的,小伙伴们,明白了不?下节继续硬起来。
原创不易,打字截图不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,动动你的金手指,早日实现财务自由