首頁>技術>

一.前面講了S7連線的握手過程,及讀取DB的演算法,今天我們講講如何寫DB區

今天手裡有1200,那就繼續用實體PLC測試,再嘗試用威綸通觸控式螢幕連線PLC進行抓包解析,首先環境準備。

硬體環境:S71200

軟體環境:威綸通EasyBuilder、TIAV16、Wireshark抓包工具、VS2019

二.開始抓包分析吧

1.電腦IP:192.168.0.227

2.PLCIP:192.168.0.50

3.用威綸通觸控式螢幕組態軟體線上模擬監控DB2.DBW2用寫入資料8

4.抓報文,老規矩從這麼多報文裡面找到有價值的資料,多次嘗試,分析

5.報文分析,由於我們操作DB區有可能操作其bool位,所以是有必要把bit位的操作考慮進去。

6.如圖分析,控制寫地址有三個位元組,多分析幾個報文看到規律第28 29 30,控制要寫的地址

高21位是控制DB號的,左移二進位制把低三位位置騰出來,或者乘以8,低3位控制bit位(2^3)不能超過8.

由於3個位元組中,前面21位是控制位元組位置的,我們獲取bit16-bit23位元組,與0xff0000獲得,再右移16位讓它可以存在高8位位元組,大端儲存方式。

整個報文位元組數

7.分析報文發現第2(高8位)、3(低8位)位元組是控制整個報文位元組數

DBW2bit 2*8=16#0010

8.分析報文看到規律第33(高8位)34(低8位)控制要寫的bit數量,一個位元組8個bit位,乘以8就是最終二進位制位。

9.我們分析多次報文,發現第11(高8位)12(低8位)位元組控制通訊參考標識,怎麼理解?透過悟性可以悟到,這東西就相當於給通訊的每一筆資料起個名字,用來區分不同筆報文。

10.其他報文前面幾講,有講了。

三.我們開始擼程式碼吧

1.接著前面程式碼寫,寫DB的演算法程式碼

2.原始碼我也貼了上來

int refercence = 888;//通訊參考標識        /// <summary>        /// 寫DB的方法位元組排序大端 參考1413筆資料        /// </summary>        /// <param name="DB">DB號</param>        /// <param name="startByte">起始位元組數</param>        /// <param name="writeBs">寫多少個位元組</param>        /// <returns></returns>          public bool WriteDB(int DB,int startByte, byte[] writeBs)        {           //固定35個位元組,加上我要寫的位元組組成報文,由於長度可變我們用list            List<byte> s7Comm = new List<byte>()            {                0x03,0x00,0x00,0x25,0x02,0xf0,0x80,0x32,0x01,0x00,                0x00,0xa0,0x00,0x00,0x0e,0x00,0x06,0x05,0x01,0x12,                0x0a,0x10,0x02,0x00,0x02,0x00,0x02,0x84,0x00,0x00,                0x40,0x00,0x04,0x00,0x10//...資料區            };//0x84代表DB區            //分析報文看到規律第2(高8位)3(低8位)控制要寫的報文長度 ,獲得位元組陣列 先轉為ushort型別是為了確定輸出位元組為2個固定35個位元組            byte[] bs = BitConverter.GetBytes((ushort)(35 + writeBs.Length));            s7Comm[02] = bs[1];            s7Comm[03] = bs[0];                refercence++; //通訊參考標識每次自增 相當於給這個報文起了個名字            bs = BitConverter.GetBytes((ushort)refercence);            s7Comm[11] = bs[1];            s7Comm[12] = bs[0];                    bs = BitConverter.GetBytes((ushort)(writeBs.Length+4));//data 長度 這裡指的item長度 固定長度4+可變長度資料            s7Comm[15] = bs[1];            s7Comm[16] = bs[0];                      bs = BitConverter.GetBytes((ushort)writeBs.Length);  //分析報文看到規律第23(高8位)24(低8位)控制要寫的位元組數            s7Comm[23] = bs[1];            s7Comm[24] = bs[0];                       bs = BitConverter.GetBytes((ushort)DB);//分析報文看到規律第25(高8位)26(低8位)控制要寫的DB號            s7Comm[25] = bs[1];            s7Comm[26] = bs[0];            //重點 分析報文看到規律第28 29 30,控制要寫的地址,高21位是控制位元組位置的,左移二進位制把低三位位置騰出來,低3位控制bit位(2^3)不能超過8            uint startByte1 = (uint)startByte << 3;                    s7Comm[28] = (byte)((startByte1 & 0xff0000) >> 16);//獲取bit16-bit23位元組,與0xff0000獲得,再右移16位讓它可以存在位元組 大端儲存                     bs = BitConverter.GetBytes((ushort)(startByte1 & 0x00ffff)); //與0xffff獲得低16位再獲取2個位元組            s7Comm[29] = bs[1];            s7Comm[30] = bs[0];                 bs = BitConverter.GetBytes((ushort)(writeBs.Length * 8)); //分析報文看到規律第33(高8位)34(低8位)控制要寫的bit數量            s7Comm[33] = bs[1];            s7Comm[34] = bs[0];                  s7Comm.AddRange(writeBs);//新增我們要寫的位元組陣列資料            S7TcpClient.Send(s7Comm.ToArray());//傳送s7報文            Thread.Sleep(100);//等待10ms給1500CPU反應時間 實際時間根據效能自己寫 或者寫智慧接收..我這裡只提供思路            byte[] s7Result = new byte[S7TcpClient.Available];//接收了多少個位元組 我們new相應的長度            S7TcpClient.Receive(s7Result);//接收位元組            if (s7Result?.Length>=21&& s7Result[21]==0xff) //0xff s7協議代表著成功,咱們也加上這個判斷            {                return true;            }            return false;        }

三.是騾子是馬測一測

1.給DB2.DBW寫個666試試

2.可以看到博圖軟體監控顯示已寫入成功

3.好了,S7協議寫程式碼已經成功了。這裡封裝的是位元組寫包括 PLC的 8位16位32位整形和32位單精度浮點等等的寫入,只不過區別是我們在上位機計算位元組陣列的方法不一樣。

四.其實S7協議的強大之處,還可以直接操作bool。我們傳統的做法是把對應的位元組,字讀上來,再進行與或運算再寫入,這樣從嚴謹角度上來說是不靠譜的,如modbus 40001區的操作。下期我們講bool量怎麼直接操作。

17
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • SpringBoot2 整合OAuth2元件,模擬第三方授權