首頁>技術>

一.前面講了S7連線的握手過程讀寫DB的位元組演算法,今天我們講講如何直接寫DB區bool位

硬體環境:S71200

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

二.開始抓包分析吧

1.電腦IP:192.168.0.227

2.PLCIP:192.168.0.50

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

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

5.程式碼分析結合上一節內容

三.寫程式碼

public bool WriteDB(int DB, int startByte, bool b, int startbit = 0)        {            //固定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區            byte[] writeBs = new byte[] { b ? (byte)1 : (byte)0 };            //分析報文看到規律第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];            s7Comm[22] = 0x01;            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];            if (startbit > 7)            {                throw new Exception("bool位範圍0-7");//拋異常 一個位元組只有8位 允許操作的二進位制是0-7位            }            //重點 分析報文看到規律第28 29 30,控制要寫的地址,高21位是控制位元組位置的,左移二進位制把低三位位置騰出來,低3位控制bit位(2^3)不能超過8            uint startByte1 = (uint)startByte << 3;            startByte1 |= (uint)startbit;//與要寫的bit位或一下,生成具體地址            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];            s7Comm[32] = 0x03;            //分析報文看到規律第33(高8位)34(低8位)控制要寫的bit數量            s7Comm[33] = 0x00;            s7Comm[34] = 0x01;            s7Comm.AddRange(writeBs);//新增我們要寫的位元組陣列資料            byte[] s7Result = SendRecive(s7Comm.ToArray());//傳送s7報文並接收            if (s7Result?.Length >= 21 && s7Result[21] == 0xff && s7Result[11] == s7Comm[11] && s7Result[12] == s7Comm[12]) //0xff s7協議代表著成功            {                return true;            }            return false;        }             public byte[] SendRecive(byte[] arry)        {            int delay = 0;            try            {                Monitor.Enter(lockS7);                int reslut = S7TcpClient.Send(arry);                while (S7TcpClient.Available == 0)                {                    Thread.Sleep(10);                    delay++;                    if (delay > MaxDelayCycle)                    {                        break;                    }                }                byte[] ResByte = new byte[S7TcpClient.Available];                reslut = S7TcpClient.Receive(ResByte);                return ResByte;            }            catch (Exception )            {                IsConnected = false;                return null;            }            finally            {                            Monitor.Exit(lockS7);            }        }

四 .測試:

五.完成

16
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 打日誌還能打出個線上Bug_ 太難了