首頁>技術>

在實際自動化工作中,我們發現西門子PLC與上位機觸控式螢幕很方便的,PLC端不用寫程式碼。用的是什麼協議呢?

一.今天我們就來解析S7協議。

1.硬體環境:S71215DCDCDC

2.軟體環境:Kepserver、VS2019、Wireshark(網路抓包工具)、TIA V16

3.說S7協議之前我們首先說說tcp協議。為什麼要說tcp協議呢?因為s7協議是在tcp協議基礎上封 裝的一層應用協議,與之對應還有,modbustcp,其底層都是tcp。

4.為什麼要用tcp協議呢?因為它是一個可靠的連線。我們知道tcp協議都有三次握手?

5.有沒有想過為什麼是三次握手?兩次四次行不行?

6.兩次模擬:

客戶端:服務端你能聽到我說話嗎?

服務端:我能聽到客戶端說話。你能聽到我說話嗎?

如果兩次,服務端無法確定客戶端收到它的訊息,如果服務端先說話,可能客戶端收不到他的話

7.四次:模擬

客戶端:服務端你能聽到我說話嗎?

服務端:我能聽到客戶端說話。你能聽到我說話嗎?

客戶端:我可以聽到服務端說話。你能聽到我說話嗎?

服務端:靠,不想跟傻子說話...

8.三次:模擬

客戶端:服務端你能聽到我說話嗎?

服務端:我能聽到客戶端說話。你能聽到我說話嗎?

客戶端:我可以聽到服務端說話,今晚去喝酒

連線OK

以上,通俗理解,如果想更深入瞭解,可以檢視TCP通訊原理.這裡先重點分析S7協議

二.S7協議分析

當我們用kepserver連線PLC時,出現以下報文資訊。

S7連線過程

2.如果看到當我們用S7協議連線PLC時,首先進行的是3次TCP握手,再分別有兩次往返握手COTP,S7COM確認。

CTOP傳送報文

3.從TKPT開始是我們需要封裝的報文,如紅色區域,前面是IP報文頭,我們不用管,底層會幫我們處理。

TKPT返回報文

4.TKPT返回報文紅色區域是有效資料。

5.然後就是S7COMM握手如圖:

S7COMM傳送報文

6.S7的返回報文其中有一項是PDU length,什麼意思呢?這個就是我們一次允許通訊的報文位元組數,我這裡是240;如博圖F1幫助,S7通訊1200對應的位元組是240.

保守最大通訊位元組數

三.擼程式碼實現

1.我們建立S7-1200.cs類,程式碼如下。

S7協議連線

 public class S71200    {        Socket S7TcpClient;        public int PDU { get;private set; }//對外開放PDU只讀屬性        /// <summary>        /// 連線S71200        /// </summary>        /// <param name="ip">PLC的IP地址</param>        /// <returns>是否連線成功</returns>        public bool Connect(string ip)        {            S7TcpClient = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立sokcet tcp連線物件            IAsyncResult asyncResult=S7TcpClient.BeginConnect( new IPEndPoint(IPAddress.Parse(ip),102 ),null,null);//非同步連線            asyncResult.AsyncWaitHandle.WaitOne(3000,true);//阻塞等待3秒            if (!asyncResult.IsCompleted)//非同步操作沒完成 就關掉tcp連線 返回失敗            {                S7TcpClient.Close();                return false;            }            //上面的socket連線相當於執行了tcp的三次握手            byte[] cotp = new byte[] //cotp報文封裝            {                0x03,0x00,0x00,0x16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC0,0x01,0x0A,0xC1,                  0x02,0x01,0x02,0xC2,0x02,0x01,0x00                };            byte[] s7comm = new byte[]//s7comm報文封裝            {                 0x03, 0x00, 0x00,0x19, 0x02, 0xf0,0x80,0x32,0x01,0x00,0x00,0xff,0xff,0x00,                0x08,0x00, 0x00, 0xf0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x7, 0x80             };            try            {                //第一次握手                S7TcpClient.Send(cotp, SocketFlags.None);                byte[] buffer = new byte[S7TcpClient.Available];                S7TcpClient.Receive(buffer,buffer.Length,SocketFlags.None);                //第二次握手                S7TcpClient.Send(s7comm, SocketFlags.None);                buffer = new byte[S7TcpClient.Available];                S7TcpClient.Receive(buffer, buffer.Length, SocketFlags.None);                if (buffer.Length == 27)                {                    PDU = (short)(buffer[25] * 256 + buffer[26]);//因為佔了兩個位元組 高8位位權256                }                return true;            }            catch (Exception)            {                return false;            }                    }    }

2.以上僅給大家學習除錯使用.

#上位機# #PLC# #觸控式螢幕# #電工交流圈# #電氣自動化#

17
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 如何用Python判斷一個檔案是否被佔用?非常實用