上一講我們講了如何連線S71200PLC,這講我們分析下如何讀取DB。
由於我今天手裡沒有1200,我安裝了Advanced用1500來模擬,大家都知道Advanced可以模擬通訊,關於如何使用Advanced,請檢視我發表的上一篇文章《西門子TIAV16模擬器Advanced安裝使用避坑》,剛好順便講講1500的連線握手協議。
言歸正傳,我們首先準備環境,工欲善其事必先利其器嘛。
硬體環境:不好意思,沒有啊。
軟體環境:Kepserver(或者其他支援S7協議的上位機)、Advanced V3.0、TIAV16、Wireshark抓包工具、VS2019
二、我們開始抓包分析:
電腦IP:192.168.0.241
S7-1500PLCIP:192.168.0.1
1.執行KepServer,我們發現還是三次TCP握手
2.我們主要關注下,COTP,S7COMM報文連線是否一致
3.我們發現COTP報文一致,那說明昨天1200連線的這部分報文是可以公用的。
4.我們發現S7COMM報文一致,那說明昨天的1200連線報文是一致的,全部可以共用
5.我們分析下讀DB報文是怎麼樣的?我們可以發現當讀DB2.db0時報文如下
6.多次分析報文看到規律第23(高8位)24(低8位)控制讀取長度
7.返回報文為資料01是我們需要的資料,從索引25開始。
8.我們嘗試改變這幾個位元組是否能達到我們的需求,建立讀程式碼
public byte[] ReadDB(int DB, int startByte, int count) { //透過檢視報文獲得讀取db2.dbx0.0讀取1個位元組的報文 byte[] s7Comm = new byte[31] { 0x03,0x00,0x00,0x1f,0x02,0xf0,0x80,0x32,0x01,0x00,0x00,0x00, 0x00,0x00,0x0e,0x00,0x00,0x04,0x01,0x12,0x0a,0x10,0x02,0x00, 0x01,0x00,0x02,0x84,0x00,0x00,0x00 }; //獲得位元組陣列 先轉為ushort型別是為了確定輸出位元組為2個 byte[] conutArry = BitConverter.GetBytes((ushort)count); //分析報文看到規律第23(高8位)24(低8位)控制讀取長度 s7Comm[23] = conutArry[1]; s7Comm[24] = conutArry[0]; //獲得位元組陣列 先轉為ushort型別是為了確定輸出位元組為2個 byte[] dbArry = BitConverter.GetBytes((ushort)DB); //分析報文看到規律第25(高8位)26(低8位)控制要讀取的DB號 s7Comm[25] = dbArry[1]; s7Comm[26] = dbArry[0]; byte[] result = new byte[count]; S7TcpClient.Send(s7Comm);//傳送s7報文 Thread.Sleep(10);//等待10ms給1500CPU反應時間 byte[] s7Result =new byte[S7TcpClient.Available]; S7TcpClient.Receive(s7Result); for (int i = 0; i < count; i++) { result[i] = s7Result[25 + i];//從第25位元組後是我們需要的報文 } return result; }
9.我們嘗試一次讀240個位元組
10.如上圖我們已經讀成功