C#實現(xiàn)上位機與歐姆龍PLC通訊(FINS)
先介紹下一些基本定義
串行通信:通過的是PLC上的串行口RS232/RS422/485口,上位機鏈接系統(tǒng) Hostlink系統(tǒng)是對于FA系統(tǒng)一種及優(yōu)化有經(jīng)濟的通信方式。
適用于一臺上位機與一臺或者多臺的PLC進行數(shù)據(jù)通信。
通訊協(xié)議分兩種
1:C-mode commands
只可以通過串口進行通訊
2:Fins commands
既可以通過串口通訊也可以通過各類網(wǎng)絡通訊(適應性較強)
本文只介紹fins通訊
fins (factory in terfave network service) 通訊協(xié)議是歐姆龍公司開發(fā)的一款自動化控制網(wǎng)絡指令/響應系統(tǒng)的通訊協(xié)議;運用FINS指令可實現(xiàn)各種網(wǎng)絡間的無縫通信
FINS幀結構
- 發(fā)送命令結構 命令碼2個字節(jié)
- 響應命令結構 命令碼2個字節(jié)
- 命令碼 01 01讀數(shù)據(jù)
- 命令碼 01 02寫數(shù)據(jù)
- 結束碼 00 00無錯誤
1、獲取PLC節(jié)點地址
上位機和PLC建立TCP通訊之后,可以發(fā)送以下命令來獲得PLC的節(jié)點地址;
幀結構見下表:
列表 | Content(十六進制) | Description(說明) |
---|---|---|
頭 | 46 49 4E 53 | ASCII分別代表的是 F I N S |
長度 | 00 00 00 0C | 從Command之后的數(shù)據(jù)包的長度 |
錯誤代碼 | 00 00 00 00 | 目前暫時沒用,因為在服務器不需要檢測內部錯誤 |
連接的節(jié)點地址 | 00000000~000000FE | 分別是0~254,當設置為0時表示自動獲取客戶端的Fins節(jié)點地址 |
2、命令碼介紹
詳細內容說明介紹見下表:
命令內容 | 命令代碼(MR SR) | 說明 | 功能 |
---|---|---|---|
訪問I/O存儲區(qū) | 01 01 | 讀內存區(qū) | 讀連續(xù)I/O存儲區(qū)字的內容 |
訪問I/O存儲區(qū) | 01 02 | 寫內存區(qū) | 寫連續(xù)I/O存儲區(qū)字的內容 |
訪問I/O存儲區(qū) | 01 03 | 填充內存區(qū) | 將相同的數(shù)據(jù)寫入指定范圍的I/O存儲器區(qū) |
訪問I/O存儲區(qū) | 01 04 | 多個存儲區(qū)讀取 | 讀取指定的非連續(xù)I/O存儲區(qū)字 |
訪問I/O存儲區(qū) | 01 05 | 存儲區(qū)傳輸 | 將連續(xù)存儲I/O存儲區(qū)字內容復制到另外的I/O存儲區(qū) |
訪問參數(shù)區(qū) | 02 01 | 讀取參數(shù)區(qū) | 讀取連續(xù)參數(shù)區(qū)字內容 |
訪問參數(shù)區(qū) | 02 02 | 寫入?yún)?shù)區(qū) | 寫入連續(xù)參數(shù)區(qū)字內容 |
訪問參數(shù)區(qū) | 02 03 | 填充參數(shù)區(qū) | 將相同數(shù)據(jù)寫入到指定范圍參數(shù)區(qū)域字 |
改變操作模式 | 04 01 | 設置CPU操作模式為RUN | 將CPU單元的操作模式更改為RUN或MONITOR |
改變操作模式 | 04 02 | 設置CPU操作模式為STOP | 將CPU單元的操作模式更改為編程 |
改變操作模式 | 06 01 | 讀取CPU單元狀態(tài) | 讀取CPU單元狀態(tài) |
錯誤日志 | 21 01 | 錯誤清除 | 清除錯誤或錯誤信息 |
錯誤日志 | 21 02 | 讀取錯誤日志 | 讀取錯誤日志 |
錯誤日志 | 21 03 | 清除錯誤日志 | 清除錯誤日志指針 |
3、I / O存儲器地址標識
區(qū)域 | 數(shù)據(jù)類型 | 存儲區(qū)代碼 | 存儲區(qū)地址范圍 | 存儲地址 | 字節(jié)長度 |
---|---|---|---|---|---|
DM | Bit | 02 | D0000000到D3276715 | 000000到7FFF0F | 1 |
DM | Word | 82 | D00000到D32767 | 000000到7FFF00 | 2 |
鑒于我們在和PLC通訊時,一般只需要進行讀取DM區(qū)寄存器操作,因為本文只介紹讀取和寫入DM區(qū)寄存器。其他的有需要的童鞋進行自己功能拓展。
舉例:
讀取DM區(qū)地址100,連續(xù)10個地址的數(shù)據(jù)
發(fā)送命令:010182006400000A
返回命令:010100000102030405060708090A
發(fā)送的命令進行說明:
- 1、01 01代表功能碼,讀連續(xù)I/O存儲區(qū)字的內容
- 2、82代表進行字操作
- 3、00 64轉成十進制就是100代表的是我們要讀取的起始地址
- 4、00000A轉成十進制就是10代表的是我們要讀取得長度
響應的命令說明
- 1、01 01代表功能碼,讀連續(xù)I/O存儲區(qū)字的內容
- 2、00 00代表結束碼,當不是00 00的時候表明數(shù)據(jù)幀不對
- 3、01 02 03 04 05 06 07 08 09 0A分別代表要讀取的十個寄存器的數(shù)據(jù)值
具體協(xié)議可以查看百度文庫:歐姆龍fins通訊協(xié)議
綜上,結合之前的博客,C#Socket客戶端:C#Socket客戶端我們可以整合得到一個歐姆龍fins的類,如下所示:
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; namespace OmrEntFINS { public class OmronFINS { /// <summary> /// 客戶端連接Socket /// </summary> private Socket clientSocket; /// <summary> /// 連接狀態(tài) /// </summary> public Boolean connected = false; /// <summary> /// 發(fā)送數(shù)據(jù) /// </summary> private Byte[] SendMess; /// <summary> /// 連接點 /// </summary> private IPEndPoint hostEndPoint; /// <summary> /// 連接信號量 /// </summary> private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false); /// <summary> /// 接受到數(shù)據(jù)時的委托 /// </summary> /// <param name="info"></param> public delegate void ReceiveMsgHandler(Byte[] info); /// <summary> /// 接收到數(shù)據(jù)時調用的事件 /// </summary> public event ReceiveMsgHandler OnMsgReceived; /// <summary> /// 開始監(jiān)聽數(shù)據(jù)的委托 /// </summary> public delegate void StartListenHandler(); /// <summary> /// 開始監(jiān)聽數(shù)據(jù)的事件 /// </summary> public event StartListenHandler StartListenThread; /// <summary> /// 發(fā)送信息完成的委托 /// </summary> /// <param name="successorfalse"></param> public delegate void SendCompleted(bool successorfalse); /// <summary> /// 發(fā)送信息完成的事件 /// </summary> public event SendCompleted OnSended; /// <summary> /// 監(jiān)聽接收的SocketAsyncEventArgs /// </summary> private SocketAsyncEventArgs listenerSocketAsyncEventArgs; int Plcport; public OmronFINS(String hostName, Int32 port, Int32 PLCStaion) { Plcport = PLCStaion; IPAddress[] addressList = Dns.GetHostAddresses(hostName); this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port); this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } /// <summary> /// 連接服務端 /// </summary> private bool Connect() { using (SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs()) { connectArgs.UserToken = this.clientSocket; connectArgs.RemoteEndPoint = this.hostEndPoint; connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect); clientSocket.ConnectAsync(connectArgs); //等待連接結果 bool autores = autoConnectEvent.WaitOne(1000); if (this.connected) { listenerSocketAsyncEventArgs = new SocketAsyncEventArgs(); byte[] receiveBuffer = new byte[1024];//設置接收buffer區(qū)大小 listenerSocketAsyncEventArgs.UserToken = clientSocket; listenerSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); listenerSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive); StartListenThread(); // SocketExtensions.SetKeepAlive(clientSocket, 3000, 1000); return true; } else return false; } } /// <summary> /// 開始監(jiān)聽線程的入口函數(shù) /// </summary> private void Listen() { (listenerSocketAsyncEventArgs.UserToken as Socket).ReceiveAsync(listenerSocketAsyncEventArgs); } public static List<SocketAsyncEventArgs> s_lst = new List<SocketAsyncEventArgs>(); /// <summary> /// 發(fā)送信息 /// </summary> /// <param name="message"></param> private void Send(Byte[] message) { if (this.connected) { Byte[] sendBuffer = message; SocketAsyncEventArgs senderSocketAsyncEventArgs = null;// new SocketAsyncEventArgs(); lock (s_lst) { if (s_lst.Count > 0) { senderSocketAsyncEventArgs = s_lst[s_lst.Count - 1]; s_lst.RemoveAt(s_lst.Count - 1); } } if (senderSocketAsyncEventArgs == null) { senderSocketAsyncEventArgs = new SocketAsyncEventArgs(); senderSocketAsyncEventArgs.UserToken = this.clientSocket; senderSocketAsyncEventArgs.RemoteEndPoint = this.hostEndPoint; senderSocketAsyncEventArgs.Completed += (object sender, SocketAsyncEventArgs _e) => { lock (s_lst) { s_lst.Add(senderSocketAsyncEventArgs); } }; } senderSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length); clientSocket.SendAsync(senderSocketAsyncEventArgs); } else { this.connected = false; } SendMess = message; } /// <summary> /// 斷開連接 /// </summary> private bool Disconnect() { bool returnDis = true; try { this.clientSocket.Shutdown(SocketShutdown.Both); this.clientSocket.Close(); //this.clientSocket.Dispose(); //clientSocket.Disconnect(true); //clientSocket.Disconnect(false); } catch (Exception) { returnDis = false; } finally { } this.connected = false; return returnDis; } /// <summary> /// 連接的完成方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnConnect(object sender, SocketAsyncEventArgs e) { this.connected = (e.SocketError == SocketError.Success); autoConnectEvent.Set(); } /// <summary> /// 接收的完成方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnReceive(object sender, SocketAsyncEventArgs e) { if (e.BytesTransferred == 0) { //Console.WriteLine("Socket is closed", Socket.Handle); if (clientSocket.Connected) { try { clientSocket.Shutdown(SocketShutdown.Both); } catch (Exception) { //client already closed } finally { if (clientSocket.Connected) { clientSocket.Close(); } } } Byte[] rs = new Byte[0]; OnMsgReceived(rs); this.connected = false; } else { byte[] buffer = new byte[e.BytesTransferred]; for (int i = 0; i < e.BytesTransferred; i++) { buffer[i] = e.Buffer[i]; } this.OnMsgReceived(buffer); Listen(); } } /// <summary> /// 發(fā)送的完成方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnSend(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { OnSended(true); } else { OnSended(false); this.ProcessError(e); } } /// <summary> /// 處理錯誤 /// </summary> /// <param name="e"></param> private void ProcessError(SocketAsyncEventArgs e) { Socket s = e.UserToken as Socket; if (s.Connected) { try { s.Shutdown(SocketShutdown.Both); } catch (Exception) { //client already closed } finally { if (s.Connected) { s.Close(); } } this.connected = false; } //throw new SocketException((Int32)e.SocketError); } #region IDisposable Members public void Dispose() { autoConnectEvent.Close(); if (this.clientSocket.Connected) { this.clientSocket.Close(); } } #endregion #region 歐姆龍通訊協(xié)議 /// <summary> /// 發(fā)送命令反饋 /// </summary> /// <param name="successorfalse"></param> void OmronFINS_OnSended(bool successorfalse) { if (!successorfalse) { } else { } } Byte PCS; Byte PLCS; int SendOrRev; int SendOrRev2; Byte[] SendBack; Byte[] RecvBack; /// <summary> /// 接受命令反饋 /// </summary> /// <param name="info"></param> void OmronFINS_OnMsgReceived(byte[] info) { if (SendmessHas) { if (info.Length >= 24) { if (int.Parse(info[23].ToString("X").Trim(), System.Globalization.NumberStyles.HexNumber) == Plcport) { PCS = info[19]; PLCS = info[23]; SendmessHas = false; } } } else { if (info.Length > 0)//PLC連接錯誤NO { if (SendOrRev2 == 1)//發(fā)送命令 { SendBack = info; SendOrRev2 = 0; } else if (SendOrRev == 2)//接受命令 { RecvBack = info; SendOrRev = 0; } } else { if (SendOrRev2 == 1)//發(fā)送命令 { SendBack = new Byte[1]; SendBack[0] = 0x00; SendOrRev2 = 0; } else if (SendOrRev == 2)//接受命令 { RecvBack = new Byte[1]; RecvBack[0] = 0x00; SendOrRev = 0; } } } } void OmronFINS_StartListenThread() { this.Listen(); } bool SendmessHas = false; /// <summary> /// 打開連接 /// </summary> /// <returns></returns> public bool OpenLinkPLC() { bool Ret = false; this.StartListenThread += new StartListenHandler(OmronFINS_StartListenThread); this.OnMsgReceived += new ReceiveMsgHandler(OmronFINS_OnMsgReceived); this.OnSended += new SendCompleted(OmronFINS_OnSended); Ret = this.Connect(); if (Ret) { SendmessHas = true; this.Send(GetPCAdress()); int addNs = 0; while (SendmessHas && addNs < 500) { Thread.Sleep(2); addNs++; } if (addNs < 500) { Ret = true; } else { Ret = false; } } return Ret; } /// <summary> /// 關閉連接 /// </summary> /// <returns></returns> public bool CloseLinkPLC() { return this.Disconnect(); } /// <summary> /// 寫入值(Word) /// </summary> /// <param name="TypeInt">起始寄存器地址</param> /// <param name="NumData">個數(shù)</param> /// <param name="IntValue">值</param> /// <returns>true,成功;false,失敗</returns> public bool WritePlcData(string TypeInt, int NumData, ref int[] IntValue) { bool sendRerun = false; if (NumData > 0) { Byte[] numData = BitConverter.GetBytes(NumData);//Use numData[0] and numData[1] Byte[] SendmessAge = new Byte[34 + NumData * 2]; if (GetType(TypeInt, 0) != 0x00 && Address != null && Address.Length > 1) { Byte[] getSendFunc = this.SetPLCvalue(PLCS, PCS, GetType(TypeInt, 0), Address[1], Address[0], 0x00, numData[1], numData[0], NumData); for (int i = 0; i < 34 + NumData * 2; i++) { if (i < 34) { SendmessAge[i] = getSendFunc[i]; } else { if ((i - 33) % 2 != 0) { Byte[] BuffInvalue = BitConverter.GetBytes(IntValue[(i - 33) / 2]); SendmessAge[i] = BuffInvalue[1]; } else { Byte[] BuffInvalue = BitConverter.GetBytes(IntValue[(i - 33) / 2 - 1]); SendmessAge[i] = BuffInvalue[0]; } //SendmessAge[i] } } SendOrRev2 = 1; this.Send(SendmessAge); int Outtime = 0; while (SendOrRev2 != 0 && this.connected && Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600 && SendBack != null) { try { //if (SendBack.Length > 1 && SendBack[26] == 0x01 && SendBack[27] == 0x02 && SendBack[28] == 0x00 && SendBack[29] == 0x00) //{ if (SendBack.Length > 1 && SendBack[26] == 0x01 && SendBack[27] == 0x02 && SendBack[28] == 0x00) { sendRerun = true; } else { sendRerun = false; } } catch (Exception) { } } else { SendOrRev2 = 0; } } } return sendRerun; } /// <summary> /// 讀取值(Word) /// </summary> /// <param name="TypeInt">起始寄存器地址</param> /// <param name="NumData">個數(shù)</param> /// <param name="IntValue">值</param> /// <returns></returns> public bool ReadPlcData(string TypeInt, int NumData, out int[] IntValue) { bool GetPlcRet = false; IntValue = new int[1]; if (NumData > 0) { IntValue = new int[NumData]; Byte[] numData = BitConverter.GetBytes(NumData);//Use numData[0] and numData[1] Byte[] RecivemessAge = new Byte[34]; if (GetType(TypeInt, 0) != 0x00 && Address != null && Address.Length > 1) { Byte[] getReciveFunc = this.GetPLCvalue(PLCS, PCS, GetType(TypeInt, 0), Address[1], Address[0], 0x00, numData[1], numData[0]); this.Send(getReciveFunc); SendOrRev = 2; int Outtime = 0; while (SendOrRev != 0 && this.connected && Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600 && RecvBack != null) { try { //if (RecvBack.Length > 1 && RecvBack[26] == 0x01 && RecvBack[27] == 0x01 && RecvBack[28] == 0x00 && RecvBack[29] == 0x00) if (RecvBack.Length == 30 + NumData * 2 && RecvBack[26] == 0x01 && RecvBack[27] == 0x01 && RecvBack[28] == 0x00) { GetPlcRet = true; for (int i = 0; i < NumData; i++) { IntValue[i] = int.Parse(RecvBack[30 + i * 2].ToString("X").PadLeft(2, '0') + RecvBack[30 + i * 2 + 1].ToString("X").PadLeft(2, '0'), System.Globalization.NumberStyles.HexNumber); } } else { GetPlcRet = false; } } catch (Exception) { } } else { SendOrRev = 0; } } } return GetPlcRet; } /// <summary> /// 讀取值(Word) /// </summary> /// <param name="TypeInt">起始寄存器地址</param> /// <param name="NumData">個數(shù)</param> /// <param name="IntValue">值</param> /// <returns></returns> public bool ReadPlcDataCIO(string TypeInt, int NumData, out int[] IntValue) { bool GetPlcRet = false; IntValue = new int[1]; if (NumData > 0) { IntValue = new int[NumData]; Byte[] numData = BitConverter.GetBytes(NumData);//Use numData[0] and numData[1] Byte[] RecivemessAge = new Byte[34]; if (GetType(TypeInt, 0) != 0x00 && Address != null && Address.Length > 1) { Byte[] getReciveFunc = this.GetPLCvalue(PLCS, PCS, GetType(TypeInt, 0), Address[1], Address[0], 0x00, numData[1], numData[0]); this.Send(getReciveFunc); SendOrRev = 2; int Outtime = 0; while (SendOrRev != 0 & this.connected & Outtime < 800) { Thread.Sleep(2); Outtime++; } if (Outtime < 800 && RecvBack != null) { //try //{ //if (RecvBack.Length > 1 && RecvBack[26] == 0x01 && RecvBack[27] == 0x01 && RecvBack[28] == 0x00 && RecvBack[29] == 0x00) if (RecvBack.Length > 30 && RecvBack[26] == 0x01 && RecvBack[27] == 0x01 && RecvBack[28] == 0x00) { GetPlcRet = true; for (int i = 0; i < NumData; i++) { IntValue[i] = int.Parse(RecvBack[30 + i * 2].ToString("X").PadLeft(2, '0') + RecvBack[30 + i * 2 + 1].ToString("X").PadLeft(2, '0'), System.Globalization.NumberStyles.HexNumber); } } else { GetPlcRet = false; } //} //catch (Exception) //{ //} } else { SendOrRev = 0; } } } return GetPlcRet; } /// <summary> /// 讀取值(Bit) /// </summary> /// <param name="TypeInt">起始寄存器地址</param> /// <param name="IntValue">值</param> /// <returns></returns> public bool ReadPlcBitData(string TypeInt, out int IntValue) { bool GetPlcRet = false; IntValue = 0; Byte[] RecivemessAge = new Byte[34]; if (GetType(TypeInt, 1) != 0x00 && Address != null && Address.Length > 1) { Byte[] getReciveFunc = this.GetPLCvalue(PLCS, PCS, GetType(TypeInt, 1), Address[1], Address[0], AddressBit[0]); this.Send(getReciveFunc); SendOrRev = 2; int Outtime = 0; while (SendOrRev != 0 & Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600) { if (RecvBack.Length > 1 && RecvBack[26] == 0x01 && RecvBack[27] == 0x01 && RecvBack[28] == 0x00 && RecvBack[29] == 0x00) { GetPlcRet = true; IntValue = int.Parse(RecvBack[30].ToString("X").PadLeft(2, '0'), System.Globalization.NumberStyles.HexNumber); } } else { SendOrRev = 0; } } return GetPlcRet; } /// <summary> /// Write值(bit) /// </summary> /// <param name="TypeInt">寄存器地址(CIOX.X)</param> /// <returns></returns> public bool WriteBitPlcData(string TypeInt, int ItemValue) { bool sendRerun = false; Byte[] SendmessAge = new Byte[35]; if (GetType(TypeInt, 1) != 0x00 && Address != null && Address.Length > 1) { Byte[] getSendFunc = this.WritePLCBitvalue(PLCS, PCS, GetType(TypeInt, 1), Address[1], Address[0], AddressBit[0]); for (int i = 0; i < 35; i++) { if (i < 32) { SendmessAge[i] = getSendFunc[i]; } else if (i == 32) { SendmessAge[i] = 0x00; } else if (i == 33) { SendmessAge[i] = 0x01; } else { if (ItemValue == 1) SendmessAge[i] = 0x01; else SendmessAge[i] = 0x00; } } this.Send(SendmessAge); SendOrRev2 = 1; int Outtime = 0; while (SendOrRev2 != 0 & Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600) { if (SendBack.Length > 1 && SendBack[26] == 0x01 && SendBack[27] == 0x02 && SendBack[28] == 0x00 && SendBack[29] == 0x00) { sendRerun = true; } } else { SendOrRev2 = 0; } } return sendRerun; } /// <summary> /// Set 值(bit) /// </summary> /// <param name="TypeInt">寄存器地址(CIOX.X)</param> /// <returns></returns> public bool SetPlcData(string TypeInt) { bool sendRerun = false; Byte[] SendmessAge = new Byte[35]; if (GetType(TypeInt, 1) != 0x00 && Address != null && Address.Length > 1) { Byte[] getSendFunc = this.SetPLCBitvalue(PLCS, PCS, GetType(TypeInt, 1), Address[1], Address[0], AddressBit[0]); for (int i = 0; i < 35; i++) { if (i < 34) { SendmessAge[i] = getSendFunc[i]; } else { SendmessAge[i] = 0x00; } } this.Send(SendmessAge); SendOrRev2 = 1; int Outtime = 0; while (SendOrRev2 != 0 & Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600) { if (SendBack.Length > 1 && SendBack[26] == 0x01 && SendBack[27] == 0x02 && SendBack[28] == 0x00 && SendBack[29] == 0x00) { sendRerun = true; } } } return sendRerun; } /// <summary> /// Rest 值(bit) /// </summary> /// <param name="TypeInt">寄存器地址(CIOX.X)</param> /// <returns></returns> public bool RestPlcData(string TypeInt) { bool sendRerun = false; Byte[] SendmessAge = new Byte[35]; if (GetType(TypeInt, 1) != 0x00 && Address != null && Address.Length > 1) { Byte[] getSendFunc = this.RstPLCBitvalue(PLCS, PCS, GetType(TypeInt, 1), Address[1], Address[0], AddressBit[0]); for (int i = 0; i < 35; i++) { if (i < 34) { SendmessAge[i] = getSendFunc[i]; } else { SendmessAge[i] = 0x00; } } this.Send(SendmessAge); SendOrRev2 = 1; int Outtime = 0; while (SendOrRev2 != 0 & Outtime < 600) { Thread.Sleep(2); Outtime++; } if (Outtime < 600) { if (SendBack.Length > 1 && SendBack[26] == 0x01 && SendBack[27] == 0x02 && SendBack[28] == 0x00 && SendBack[29] == 0x00) { sendRerun = true; } } } return sendRerun; } Byte[] Address; Byte[] AddressBit; private Byte GetType(string TypeInt, int SizeofInt) { Byte ms = 0x00; if (TypeInt.IndexOf("D") == 0 | TypeInt.IndexOf("d") == 0) { if (SizeofInt == 0) { ms = 0x82; if (TypeInt.IndexOf(".") == -1) Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.Length - 1))); else { Address = new Byte[1]; AddressBit = new Byte[1]; } } else { ms = 0x02; if (TypeInt.IndexOf(".") > 1) { Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.IndexOf(".") - 1))); AddressBit = BitConverter.GetBytes(int.Parse(TypeInt.Substring(TypeInt.IndexOf(".") + 1, TypeInt.Length - TypeInt.IndexOf(".") - 1))); } else { Address = new Byte[1]; AddressBit = new Byte[1]; } } } else if (TypeInt.IndexOf("CIO") == 0 | TypeInt.IndexOf("cio") == 0) { if (SizeofInt == 0) { ms = 0xB0; if (TypeInt.IndexOf(".") == -1) Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(3, TypeInt.Length - 3))); else { Address = new Byte[1]; AddressBit = new Byte[1]; } } else { ms = 0x30; if (TypeInt.IndexOf(".") > 3) { Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(3, TypeInt.IndexOf(".") - 3))); AddressBit = BitConverter.GetBytes(int.Parse(TypeInt.Substring(TypeInt.IndexOf(".") + 1, TypeInt.Length - TypeInt.IndexOf(".") - 1))); } else { Address = new Byte[1]; AddressBit = new Byte[1]; } } } else if (TypeInt.IndexOf("W") == 0 | TypeInt.IndexOf("w") == 0) { if (SizeofInt == 0) { ms = 0xB1; if (TypeInt.IndexOf(".") == -1) Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.Length - 1))); else { Address = new Byte[1]; AddressBit = new Byte[1]; } } else { ms = 0x31; if (TypeInt.IndexOf(".") > 1) { Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.IndexOf(".") - 1))); AddressBit = BitConverter.GetBytes(int.Parse(TypeInt.Substring(TypeInt.IndexOf(".") + 1, TypeInt.Length - TypeInt.IndexOf(".") - 1))); } else { Address = new Byte[1]; AddressBit = new Byte[1]; } } } else if (TypeInt.IndexOf("H") == 0 | TypeInt.IndexOf("h") == 0) { if (SizeofInt == 0) { ms = 0xB2; if (TypeInt.IndexOf(".") == -1) Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.Length - 1))); else { Address = new Byte[1]; AddressBit = new Byte[1]; } } else { ms = 0x32; if (TypeInt.IndexOf(".") > 1) { Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.IndexOf(".") - 1))); AddressBit = BitConverter.GetBytes(int.Parse(TypeInt.Substring(TypeInt.IndexOf(".") + 1, TypeInt.Length - TypeInt.IndexOf(".") - 1))); } else { Address = new Byte[1]; AddressBit = new Byte[1]; } } } else if (TypeInt.IndexOf("A") == 0 | TypeInt.IndexOf("a") == 0) { if (SizeofInt == 0) { ms = 0xB3; if (TypeInt.IndexOf(".") == -1) Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.Length - 1))); else { Address = new Byte[1]; AddressBit = new Byte[1]; } } else { ms = 0x33; if (TypeInt.IndexOf(".") > 1) { Address = BitConverter.GetBytes(int.Parse(TypeInt.Substring(1, TypeInt.IndexOf(".") - 1))); AddressBit = BitConverter.GetBytes(int.Parse(TypeInt.Substring(TypeInt.IndexOf(".") + 1, TypeInt.Length - TypeInt.IndexOf(".") - 1))); } else { Address = new Byte[1]; AddressBit = new Byte[1]; } } } return ms; } /// <summary> /// Get PLC DA1 SNA1 /// </summary> /// <returns></returns> private Byte[] GetPCAdress() { Byte[] ReturnGetPC = new Byte[20]; ReturnGetPC[0] = 0x46;//f ReturnGetPC[1] = 0x49;//i ReturnGetPC[2] = 0x4E;//n ReturnGetPC[3] = 0x53;//s ReturnGetPC[4] = 0x00; ReturnGetPC[5] = 0x00; ReturnGetPC[6] = 0x00; ReturnGetPC[7] = 0x0C; ReturnGetPC[8] = 0x00; ReturnGetPC[9] = 0x00; ReturnGetPC[10] = 0x00; ReturnGetPC[11] = 0x00; ReturnGetPC[12] = 0x00; ReturnGetPC[13] = 0x00; ReturnGetPC[14] = 0x00; ReturnGetPC[15] = 0x00; ReturnGetPC[16] = 0x00; ReturnGetPC[17] = 0x00; ReturnGetPC[18] = 0x00; ReturnGetPC[19] = 0x00; return ReturnGetPC; } /// <summary> /// Read Word /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <param name="DataNum1"></param> /// <param name="DataNum2"></param> /// <returns></returns> private Byte[] GetPLCvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3, Byte DataNum1, Byte DataNum2) { Byte[] SendFun = new Byte[34]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = 0x1A; SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x01; SendFun[27] = 0x01; SendFun[28] = DataValue; SendFun[29] = Address1; SendFun[30] = Address2; SendFun[31] = Address3; SendFun[32] = DataNum1; SendFun[33] = DataNum2; return SendFun; } /// <summary> /// Write Word /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <param name="DataNum1"></param> /// <param name="DataNum2"></param> /// <returns></returns> private Byte[] SetPLCvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3, Byte DataNum1, Byte DataNum2, int num) { Byte[] SendFun = new Byte[34]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = (byte)(26 + 2 * num); SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x01; SendFun[27] = 0x02; SendFun[28] = DataValue; SendFun[29] = Address1; SendFun[30] = Address2; SendFun[31] = Address3; SendFun[32] = DataNum1; SendFun[33] = DataNum2; return SendFun; } /// <summary> /// Read Bit /// /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <param name="DataNum1"></param> /// <param name="DataNum2"></param> /// <returns></returns> private Byte[] GetPLCvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3) { Byte[] SendFun = new Byte[34]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = 0x1A; SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x01; SendFun[27] = 0x01; SendFun[28] = DataValue; SendFun[29] = Address1; SendFun[30] = Address2; SendFun[31] = Address3; SendFun[32] = 0x00; SendFun[33] = 0x01; return SendFun; } /// <summary> /// Write Bit /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <returns></returns> private Byte[] WritePLCBitvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3) { Byte[] SendFun = new Byte[32]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = 0x1B; SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x01; SendFun[27] = 0x02; SendFun[28] = DataValue; SendFun[29] = Address1; SendFun[30] = Address2; SendFun[31] = Address3; return SendFun; } /// <summary> /// Set Bit /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <returns></returns> private Byte[] SetPLCBitvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3) { Byte[] SendFun = new Byte[35]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = 0x1B; SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x23; SendFun[27] = 0x01; SendFun[28] = 0x01; SendFun[29] = 0x00; SendFun[30] = 0x01; SendFun[31] = DataValue; SendFun[32] = Address1; SendFun[33] = Address2; SendFun[34] = Address3; return SendFun; } /// <summary> /// RST Bit /// </summary> /// <param name="DA1"></param> /// <param name="SA1"></param> /// <param name="DataValue"></param> /// <param name="Address1"></param> /// <param name="Address2"></param> /// <param name="Address3"></param> /// <returns></returns> private Byte[] RstPLCBitvalue(Byte DA1, Byte SA1, Byte DataValue, Byte Address1, Byte Address2, Byte Address3) { Byte[] SendFun = new Byte[35]; SendFun[0] = 0x46; SendFun[1] = 0x49; SendFun[2] = 0x4E; SendFun[3] = 0x53; SendFun[4] = 0x00; SendFun[5] = 0x00; SendFun[6] = 0x00; SendFun[7] = 0x1B; SendFun[8] = 0x00; SendFun[9] = 0x00; SendFun[10] = 0x00; SendFun[11] = 0x02; SendFun[12] = 0x00; SendFun[13] = 0x00; SendFun[14] = 0x00; SendFun[15] = 0x00; SendFun[16] = 0x80; SendFun[17] = 0x00; SendFun[18] = 0x02; SendFun[19] = 0x00; SendFun[20] = DA1; SendFun[21] = 0x00; SendFun[22] = 0x00; SendFun[23] = SA1; SendFun[24] = 0x00; SendFun[25] = 0x01; SendFun[26] = 0x23; SendFun[27] = 0x01; SendFun[28] = 0x01; SendFun[29] = 0x00; SendFun[30] = 0x00; SendFun[31] = DataValue; SendFun[32] = Address1; SendFun[33] = Address2; SendFun[34] = Address3; return SendFun; } #endregion } }
至此,我們就可以用上述的類和歐姆龍PLC進行FINS通訊。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。