<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      基于歐姆龍PLC#FinsTcp協議上位機通訊(二)-C#通訊模塊開發

        上一篇我們介紹了如何配置連接PLC(注意網線記得插到PLC以太網口!!!還有一個好像是伺服的網口不要插錯了),接下來將介紹歐姆FinsTcp協議及使用C#實現過程。

      1. FinsTcp協議報文格式

       

       

       獲取PLC節點地址

       

       

       FINS command

       

       

       IO存儲器地址標識

       

       

       

        2.實現過程

      以上為FinsTCP協議主要核心內容,代碼原理很簡單就是通過SOCKET /TCP IP,發送連接、讀取、寫入報文數據,接收解析返回數據;

      • 基于TcpClient的發送與接收Byte[]方法

      發送BYTE

       1 public static bool SendData(out string msg,TcpClient tcpClient,byte[] sd)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 tcpClient.GetStream().Write(sd, 0, sd.Length);
       7                 return true;
       8             }
       9             catch(Exception ex)
      10             {
      11                 msg = ex.Message;
      12                 return false;
      13             }
      14         }
      View Code

      接收BYTE

       1         public static bool ReceiveData(out string msg, TcpClient tcpClient,byte[] rd)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 int index = 0;
       7                 do
       8                 {
       9                     int len = tcpClient.GetStream().Read(rd, index, rd.Length - index);
      10                     if (len == 0)
      11                         return false;//這里控制讀取不到數據時就跳出,網絡異常斷開,數據讀取不完整。
      12                     else
      13                         index += len;
      14                 } while (index < rd.Length);
      15                 return true;
      16             }
      17             catch(Exception ex)
      18             {
      19                 msg = ex.Message;
      20                 return false;
      21             }
      22         }
      View Code
      • 基于Socket的發送與接收Byte[]方法

      發送BYTE

       1         public bool SendData(out string msg,byte[] sd)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 if(!(IsConnected && _Socket != null && _Socket.Connected))
       7                 {
       8                     if(!Connect(out msg))
       9                     {
      10                         Thread.Sleep(40);
      11                         if (!Connect(out msg)) return false;
      12                     }
      13                 }
      14                 _Socket.Send(sd, sd.Length, 0);
      15                 return true;
      16             }
      17             catch (Exception ex)
      18             {
      19                 msg = ex.Message;
      20                 Disconnect(out string _msg);
      21                 return false;
      22             }
      23         }
      View Code

      接收BYTE

       1 public bool ReceiveData(out string msg,byte[] rd)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 if (!(IsConnected && _Socket != null && _Socket.Connected))
       7                 {
       8                     if (!Connect(out msg))
       9                     {
      10                         Thread.Sleep(40);
      11                         if (!Connect(out msg)) return false;
      12                     }
      13                 }
      14                 _Socket.Receive(rd, rd.Length, 0);
      15                 return true;
      16             }
      17             catch (Exception ex)
      18             {
      19                 msg = ex.Message;
      20                 Disconnect(out string _msg);
      21                 return false;
      22             }
      23         }
      View Code

      這里由于當初寫時的想法不同,有的在外層寫了連接狀態判斷有的寫在發送接收方法里面;

      • 網絡判斷
      1      public static bool PingCheck(string ip, int connectTimeout = 10000)
      2         {
      3             Ping ping = new Ping();
      4             PingReply pr = ping.Send(ip, connectTimeout);
      5             if (pr.Status == IPStatus.Success)
      6                 return true;
      7             else
      8                 return false;
      9         }
      View Code

      歐姆龍PLC的連接與初始化

      協議

       1   private byte[] HandShake()
       2         {
       3             byte[] array = new byte[20];
       4             array[0] = 0x46;
       5             array[1] = 0x49;
       6             array[2] = 0x4E;
       7             array[3] = 0x53;
       8 
       9             array[4] = 0;
      10             array[5] = 0;
      11             array[6] = 0;
      12             array[7] = 0x0C;
      13 
      14             array[8] = 0;
      15             array[9] = 0;
      16             array[10] = 0;
      17             array[11] = 0;
      18 
      19             array[12] = 0;
      20             array[13] = 0;
      21             array[14] = 0;
      22             array[15] = 0;
      23 
      24             array[16] = 0;
      25             array[17] = 0;
      26             array[18] = 0;
      27             array[19] = 0;
      28 
      29             return array;
      30         }
      View Code
       1 private byte[] FinsCommand(RorW rw, PlcMemory mr, MemoryType mt, short ch, short offset, short cnt)
       2         {
       3             byte[] array = new byte[34];
       4             //TCP FINS header
       5             array[0] = 0x46;//F
       6             array[1] = 0x49;//I
       7             array[2] = 0x4E;//N
       8             array[3] = 0x53;//S
       9 
      10             array[4] = 0;//cmd length
      11             array[5] = 0;
      12 
      13             if (rw == RorW.Read)
      14             {
      15                 array[6] = 0;
      16                 array[7] = 0x1A;//26
      17             }
      18             else
      19             {
      20                 //寫數據的時候一個字占兩個字節,而一個位只占一個字節
      21                 if (mt == MemoryType.Word)
      22                 {
      23                     array[6] = (byte)((cnt * 2 + 26) / 256);
      24                     array[7] = (byte)((cnt * 2 + 26) % 256);
      25                 }
      26                 else
      27                 {
      28                     array[6] = 0;
      29                     array[7] = 0x1B;
      30                 }
      31             }
      32 
      33             array[8] = 0;//frame command
      34             array[9] = 0;
      35             array[10] = 0;
      36             array[11] = 0x02;
      37 
      38             array[12] = 0;
      39             array[13] = 0;
      40             array[14] = 0;
      41             array[15] = 0;
      42             //command frame header
      43             array[16] = 0x80;//ICF
      44             array[17] = 0x00;//RSV
      45             array[18] = 0x02;//GCT, less than 8 network layers
      46             array[19] = 0x00;//DNA, local network
      47 
      48             array[20] = PLCNode;//DA1
      49             array[21] = 0x00;//DA2, CPU unit
      50             array[22] = 0x00;//SNA, local network
      51             array[23] = PCNode;//SA1
      52 
      53             array[24] = 0x00;//SA2, CPU unit
      54             array[25] = 0xFF;
      55 
      56             //指令碼
      57             if (rw == RorW.Read)
      58             {
      59                 array[26] = 0x01;//cmdCode--0101
      60                 array[27] = 0x01;
      61             }
      62             else
      63             {
      64                 array[26] = 0x01;//write---0102
      65                 array[27] = 0x02;
      66             }
      67             //地址
      68             //array[28] = (byte)mr;
      69             array[28] = GetMemoryCode(mr, mt);
      70             array[29] = (byte)(ch / 256);
      71             array[30] = (byte)(ch % 256);
      72             array[31] = (byte)offset;
      73 
      74             array[32] = (byte)(cnt / 256);
      75             array[33] = (byte)(cnt % 256);
      76 
      77             return array;
      78         }
      View Code

      這邊連接初始化時需要獲取網絡節點號

       1  public bool Open(out string msg)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 if (!SocketHelper.PingCheck(Ip, ConnectTimeout))
       7                 {
       8                     msg = "網絡故障!";
       9                     return false;
      10                 }
      11                 System.Diagnostics.Stopwatch sp = new System.Diagnostics.Stopwatch();
      12                 sp.Start();
      13                 tcpClient = new TcpClient();
      14                 tcpClient.ReceiveTimeout = ReceiveTimeout;
      15                 tcpClient.SendTimeout = SendTimeout;
      16                 tcpClient.Connect(Ip, Port);
      17                 Thread.Sleep(10);
      18                 if (!tcpClient.Connected)
      19                 {
      20                     throw new ApplicationException($"未連接到{Ip}");
      21                 }
      22                 if (!SocketHelper.SendData(out msg, tcpClient, HandShake()))
      23                 {
      24                     msg = $"連接,數據寫入失敗:{msg}!";
      25                     return false;
      26                 }
      27 
      28                 //開始讀取返回信號
      29                 byte[] buffer = new byte[24];
      30                 if (!SocketHelper.ReceiveData(out msg, tcpClient, buffer))
      31                 {
      32                     msg = $"連接握手信號接收失敗:{msg}!";
      33                     return false;
      34                 }
      35 
      36                 if (buffer[15] != 0)//TODO:這里的15號是不是ERR信息暫時不能完全肯定
      37                 {
      38                     msg = $"超過最大連接數或內部連接錯誤";
      39                     return false;
      40                 }
      41                 PCNode = buffer[19];
      42                 PLCNode = buffer[23];
      43                 msg = $"連接[{Ip}]成功,耗時{sp.Elapsed.TotalMilliseconds.ToString()}ms";
      44                 return true;
      45 
      46             }
      47             catch (Exception ex)
      48             {
      49                 Close(out string _msg);//連接斷開,重試
      50                 msg = $"連接失敗:{ex.Message}";
      51                 return false;
      52             }
      53         }
      View Code

      讀取方法

       1 public bool ReadWordsByte_B(out string msg, PlcMemory mr, int startIndex, int len, out byte[] reData)
       2         {
       3             msg = string.Empty; reData = new byte[0];
       4             try
       5             {
       6                 System.Diagnostics.Stopwatch sp = new System.Diagnostics.Stopwatch();
       7                 sp.Start();
       8                 int i = 0;
       9                 for (int index = startIndex; index < startIndex + len; index += OmronConsts.MAXREADDATE)
      10                 {
      11                     int _newLen = len + startIndex- index;
      12                     if (_newLen > OmronConsts.MAXREADDATE) _newLen = OmronConsts.MAXREADDATE;
      13                     i++;
      14                     byte[] array = FinsCmd(RorW.Read, mr, MemoryType.Word, (short)(index/2), 00, (short)(_newLen/2));
      15 
      16                     if (!SocketHelper.SendData(out msg, tcpClient, array))
      17                     {
      18                         msg = $"讀取,數據寫入失敗[{i}次]:{msg}!";
      19                         return false;
      20                     }
      21                     byte[] buffer = new byte[30 + _newLen];//用于接收數據的緩存區大小
      22                     if (!SocketHelper.ReceiveData(out msg, tcpClient, buffer))
      23                     {
      24                         msg = $"讀取,數據接收失敗[{i}次]:{msg}!";
      25                         return false;
      26                     }
      27                     //命令返回成功,繼續查詢是否有錯誤碼,然后在讀取數據
      28                     if (buffer[11] == 3)
      29                     {
      30                         if (!ErrorCode.CheckHeadError(buffer[15], out msg))
      31                         {
      32                             msg = $"讀取數據失敗[{i}次]:{msg}!";
      33                             return false;
      34                         }
      35                     }
      36                     //endcode為fins指令的返回錯誤碼
      37                     if (!ErrorCode.CheckEndCode(buffer[28], buffer[29], out msg))
      38                     {
      39                         msg = $"讀取數據失敗[{i}次]:{msg}!";
      40                         return false;
      41                     }
      42                     byte[] _bytes = new byte[_newLen];
      43 
      44                     Array.Copy(buffer, 30, _bytes, 0, _newLen);
      45 
      46                     reData = reData.Concat(_bytes).ToArray();
      47                 }
      48 
      49                 msg = $"讀取({reData.Length})字節數據成功,耗時{sp.Elapsed.TotalMilliseconds.ToString()}ms,{i}次讀取";
      50                 return true;
      51             }
      52             catch (Exception ex)
      53             {
      54                 msg = ex.Message;
      55                 return false;
      56             }
      57         }
      View Code

      寫入方法

       1  public bool WriteWordsByte_B(out string msg, PlcMemory mr, short startIndex, byte[] inData)
       2         {
       3             msg = string.Empty;
       4             try
       5             {
       6                 if (inData == null || inData.Length < 1)
       7                 {
       8                     msg = "寫入數據失敗,寫入數據為空!";
       9                     return false;
      10                 }
      11                 //奇數補零,寫入數據必須為一個字
      12                 if ((inData.Length % 2) > 0)
      13                 {
      14                     inData = inData.Concat(new byte[1] { 0 }).ToArray();
      15                 }
      16                 //寫入長度大于2000
      17                 System.Diagnostics.Stopwatch sp = new System.Diagnostics.Stopwatch();
      18                 sp.Start();
      19                 int i = 0;int len = inData.Length;
      20                 for (int index= startIndex; index < startIndex  + len; index += OmronConsts.MAXRWRIDATE)
      21                 {
      22                     int _newLen = len + startIndex - index;
      23                     if (_newLen > OmronConsts.MAXRWRIDATE) _newLen = OmronConsts.MAXRWRIDATE;
      24                     i++;
      25                     byte[] nData = new byte[_newLen];
      26 
      27                     Array.Copy(inData, index- startIndex, nData,0, _newLen);
      28 
      29                     byte[] dataHead = FinsCmd(RorW.Write, mr, MemoryType.Word, (short)(index/2), 00, (short)(_newLen /2));
      30 
      31                     byte[] zData = new byte[_newLen+34];
      32                    
      33                     dataHead.CopyTo(zData,0);
      34                    
      35                     nData.CopyTo(zData, 34);
      36 
      37                     if (!SocketHelper.SendData(out msg, tcpClient, zData))
      38                     {
      39                         msg = $"寫入,數據寫入失敗[{i}次]:{msg}!";
      40                         return false;
      41                     }
      42                     byte[] rBuffer= new byte[30];
      43                     if (!SocketHelper.ReceiveData(out msg, tcpClient, rBuffer))
      44                     {
      45                         msg = $"寫入,數據接收失敗[{i}次]:{msg}!";
      46                         return false;
      47                     }
      48                     if (rBuffer[11] == 3)
      49                     {
      50                         if (!ErrorCode.CheckHeadError(rBuffer[15], out msg))
      51                         {
      52                             msg = $"寫入數據失敗[{i}次]:{msg}!";
      53                             return false;
      54                         }
      55                     }
      56                     if (!ErrorCode.CheckEndCode(rBuffer[28], rBuffer[29], out msg))
      57                     {
      58                         msg = $"寫入數據失敗[{i}次]:{msg}!";
      59                         return false;
      60                     }
      61 
      62                 }
      63                 msg = $"寫入({len})字節數據成功,耗時{sp.Elapsed.TotalMilliseconds.ToString()}ms,{i}次寫入";
      64                 return true;
      65             }
      66             catch (Exception ex)
      67             {
      68                 msg = ex.Message;
      69                 return false;
      70             }
      71         }
      View Code

      通過讀取與寫入方法就完成了對歐姆龍PLC的交互

      測試結果

       

       

       

       

      完畢!

       

      posted @ 2022-01-05 09:30  豆腐檸檬  閱讀(5340)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 孟州市| 亚洲午夜亚洲精品国产成人| 国产第一页浮力影院入口| 锦州市| 中文国产日韩欧美二视频| 亚洲WWW永久成人网站| 成人午夜激情在线观看| 亚洲综合一区二区三区在线| 国产成人精品无码播放| 章丘市| 九九热在线免费播放视频| 天堂V亚洲国产V第一次| 国产精品视频一区不卡| 日本一区二区三区四区黄色| 国产在线无码视频一区二区三区| 石河子市| 亚洲国产精品高清久久久| 亚洲欧美在线看片AI| 蜜臀久久精品亚洲一区| 亚洲国产综合精品2020| 男女性高爱潮免费网站| 日韩欧美在线综合网另类| 成人资源网亚洲精品在线| 乱码精品一区二区三区| 亚洲国产精品第一二三区| 色天天天综合网色天天| 日韩有码av中文字幕| 亚洲第一狼人成人综合网| 国产精品欧美福利久久| 婷婷色综合成人成人网小说| 激情综合网激情综合网五月| 国产色无码专区在线观看| 巨胸爆乳美女露双奶头挤奶| 中文文字幕文字幕亚洲色| 国产精品美女自慰喷水| 1精品啪国产在线观看免费牛牛| 亚洲成亚洲成网中文字幕| 酒店大战丝袜高跟鞋人妻| 亚洲国产免费图区在线视频| 亚洲精品午夜国产VA久久成人 | 兴国县|