C#上位机与欧姆龙PLC通讯(FINS)
C#上位机与欧姆龙PLC通讯
先介绍下一些基本定义:
串行通信:通过的是PLC上的串行口RS232/RS422/485口,上位机链接系统 Hostlink系统是对于FA系统一种及优化有经济的通信方式。适用于一台上位机与一台或者多台的PLC进行数据通信。
通讯协议分两种
1:C-mode commands
只可以通过串口进行通讯
2:Fins commands
既可以通过串口通讯也可以通过各类网络通讯(适应性较强)
本文只介绍fins通讯
fins (factory in terfave network service) 通讯协议是欧姆龙公司开发的一款自动化控制网络指令/响应系统的通讯协议;运用FINS指令可实现各种网络间的无缝通信
FINS帧结构
发送命令结构 命令码2个字节
响应命令结构 命令码2个字节
命令码 01 01读数据
命令码 01 02写数据
结束码 00 00无错误
1、获取PLC节点地址
上位机和PLC建立TCP通讯之后,可以发送以下命令来获得PLC的节点地址;
帧结构见下表:
列表 | Content(十六进制) | Description(说明) |
---|---|---|
头 | 46 49 4E 53 | ASCII分别代表的是 F I N S |
长度 | 00 00 00 0C | 从Command之后的数据包的长度 |
错误代码 | 00 00 00 00 | 目前暂时没用,因为在服务器不需要检测内部错误 |
连接的节点地址 | 00000000~000000FE | 分别是0~254,当设置为0时表示自动获取客户端的Fins节点地址 |
2、命令码介绍
详细内容说明介绍见下表:
命令内容 | 命令代码(MR SR) | 说明 | 功能 |
---|---|---|---|
访问I/O存储区 | 01 01 | 读内存区 | 读连续I/O存储区字的内容 |
访问I/O存储区 | 01 02 | 写内存区 | 写连续I/O存储区字的内容 |
访问I/O存储区 | 01 03 | 填充内存区 | 将相同的数据写入指定范围的I/O存储器区 |
访问I/O存储区 | 01 04 | 多个存储区读取 | 读取指定的非连续I/O存储区字 |
访问I/O存储区 | 01 05 | 存储区传输 | 将连续存储I/O存储区字内容复制到另外的I/O存储区 |
访问参数区 | 02 01 | 读取参数区 | 读取连续参数区字内容 |
访问参数区 | 02 02 | 写入参数区 | 写入连续参数区字内容 |
访问参数区 | 02 03 | 填充参数区 | 将相同数据写入到指定范围参数区域字 |
改变操作模式 | 04 01 | 设置CPU操作模式为RUN | 将CPU单元的操作模式更改为RUN或MONITOR |
改变操作模式 | 04 02 | 设置CPU操作模式为STOP | 将CPU单元的操作模式更改为编程 |
改变操作模式 | 06 01 | 读取CPU单元状态 | 读取CPU单元状态 |
错误日志 | 21 01 | 错误清除 | 清除错误或错误信息 |
错误日志 | 21 02 | 读取错误日志 | 读取错误日志 |
错误日志 | 21 03 | 清除错误日志 | 清除错误日志指针 |
3、I / O存储器地址标识
区域 | 数据类型 | 存储区代码 | 存储区地址范围 | 存储地址 | 字节长度 |
---|---|---|---|---|---|
DM | Bit | 02 | D0000000到D3276715 | 000000到7FFF0F | 1 |
DM | Word | 82 | D00000到D32767 | 000000到7FFF00 | 2 |
鉴于我们在和PLC通讯时,一般只需要进行读取DM区寄存器操作,因为本文只介绍读取和写入DM区寄存器。其他的有需要的童鞋进行自己功能拓展。
举例:
1、读取DM区地址100,连续10个地址的数据
发送命令:010182006400000A
返回命令:010100000102030405060708090A
发送的命令进行说明:
1、01 01代表功能码,读连续I/O存储区字的内容
2、82代表进行字操作
3、00 64转成十进制就是100代表的是我们要读取的起始地址
4、00000A转成十进制就是10代表的是我们要读取得长度
响应的命令说明
1、01 01代表功能码,读连续I/O存储区字的内容
2、00 00代表结束码,当不是00 00的时候表明数据帧不对
3、01 02 03 04 05 06 07 08 09 0A分别代表要读取的十个寄存器的数据值
具体协议可以查看百度文库:欧姆龙fins通讯协议
综上,结合之前的博客,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>/// 连接状态/// </summary>public Boolean connected = false;/// <summary>/// 发送数据/// </summary>private Byte[] SendMess;/// <summary>/// 连接点/// </summary>private IPEndPoint hostEndPoint;/// <summary>/// 连接信号量/// </summary>private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);/// <summary>/// 接受到数据时的委托/// </summary>/// <param name="info"></param>public delegate void ReceiveMsgHandler(Byte[] info);/// <summary>/// 接收到数据时调用的事件/// </summary>public event ReceiveMsgHandler OnMsgReceived;/// <summary>/// 开始监听数据的委托/// </summary>public delegate void StartListenHandler();/// <summary>/// 开始监听数据的事件/// </summary>public event StartListenHandler StartListenThread;/// <summary>/// 发送信息完成的委托/// </summary>/// <param name="successorfalse"></param>public delegate void SendCompleted(bool successorfalse);/// <summary>/// 发送信息完成的事件/// </summary>public event SendCompleted OnSended;/// <summary>/// 监听接收的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区大小listenerSocketAsyncEventArgs.UserToken = clientSocket;listenerSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);listenerSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);StartListenThread();// SocketExtensions.SetKeepAlive(clientSocket, 3000, 1000);return true;}elsereturn false;}}/// <summary>/// 开始监听线程的入口函数/// </summary>private void Listen(){(listenerSocketAsyncEventArgs.UserToken as Socket).ReceiveAsync(listenerSocketAsyncEventArgs);}public static List<SocketAsyncEventArgs> s_lst = new List<SocketAsyncEventArgs>();/// <summary>/// 发送信息/// </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>/// 发送的完成方法/// </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 Memberspublic void Dispose(){autoConnectEvent.Close();if (this.clientSocket.Connected){this.clientSocket.Close();}}#endregion#region 欧姆龙通讯协议/// <summary>/// 发送命令反馈/// </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)//发送命令{SendBack = info;SendOrRev2 = 0;}else if (SendOrRev == 2)//接受命令{RecvBack = info;SendOrRev = 0;}}else{if (SendOrRev2 == 1)//发送命令{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">个数</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">个数</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">个数</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;elseSendmessAge[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;//fReturnGetPC[1] = 0x49;//iReturnGetPC[2] = 0x4E;//nReturnGetPC[3] = 0x53;//sReturnGetPC[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通讯。下一篇我会分享和介绍欧姆龙串口的通讯协议。
C#上位机与欧姆龙PLC通讯(FINS)相关推荐
- C#上位机和松下PLC通讯
C#上位机和松下PLC通讯 1.前言 也好久没回来看博客了,看大家对于其他的PLC的需求都是有的,说明搞我们工业控制这一行的人也是很多的.刚好最近基于项目需要,一些新的东西,需要和松下PLC的FP系列 ...
- wincc上位机与1200组态步骤_组态上位机WINCC与PLC通讯连接
WINCC 与 PLC 通讯连接 1 . STEP 7 硬件组态 STEP7 设置 MPI 通讯, 2 .安装 CP5611 通讯板卡 3 .添加驱动程序和系统参数设置 打开 WINCC 工程在 Ta ...
- 上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,
上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通讯,, ...
- 上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯
上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通讯,, ...
- 上位机与PLC 通讯源码DEMO 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制
上位机与PLC 通讯源码DEMO 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通 ...
- PLC通讯实现-C#实现欧姆龙以太网通讯FINS(二)
PLC通讯实现-C#实现欧姆龙以太网通讯FINS(二) 背景 抽象设计 欧姆龙以太网通讯实现FINS 背景 本人近十年的工作都与工业软件相关.其中工控系统开发过程中有一个必要环节就是跟各大厂商的PLC ...
- 【无标题】C#上位机与三菱PLC FX2NC通讯方法
*** C#上位机与三菱PLC FX2NC通讯方法*** 第一步从官网中下载MX COMPONENT并安装好; 第二步从安装好的MX COMPONENT路径中找到"Samples" ...
- 欧姆龙plc通讯协议格式
欧姆龙CPM1A型plc与上位计算机通信的顺序是上位机先发出命令信息给PLC,PLC返回响应信息给上位 机.每次通信发送/接受的一组数据称为一"帧".帧由少于131个字符的数据构成 ...
- 欧姆龙 PLC通讯协议
https://blog.csdn.net/sgmcumt/article/details/87435778 fins 欧姆龙 PLC通讯协议
- 安川与欧姆龙Plc通讯设置方法
安川与欧姆龙Plc通讯设置方法 id=609745949439&
最新文章
- go语言实现简易ftp客户端
- 王石:人生60岁才是开始
- “供应链”之后,传统零售如何会战“服务链”?
- showModalDialog和showModelessDialog缓存问题,参数详解,
- 全卷积网络FCN详解
- tomcat下只有.class文件 没有java文件_解决tomcat发布工程后,WEB-INF/classes下文件不编译的问题...
- 【转】 Android 屏幕切换总结
- vue从url中获取token并加入到 请求头里_BATJ都会用到的接口鉴权cookie、session 和token...
- LeetCode 392. 判断子序列(双指针二分查找)
- apache httpd配置后启动失败或域名绑定无效等问题解决方法
- python n个list如何组成矩阵_python和c++通信示例
- java左移负数位_java的左移运算符和右移运算符
- 2021年影响会计人员的十大信息技术榜单出炉,RPA再次登榜
- 模拟淘宝侧边服务模块鼠标悬停效果的三种实现方式总结
- 黑马程序员入学Java知识——精华总结
- html中怎么把h标签左移,基础标签--h、p、a、hr、br、img、base
- php中.=是什么意思,javascript中$符号是什么意思?
- php解析json转数组,php json转数组出错
- 腾讯音乐(K歌)的粗排模型
- Cerea学习,包含示例代码
热门文章
- b和kb的换算_b和kb的换算(b换算成kb)
- 一文带你由浅入深Netty异步非阻塞世界
- excel学习-sumifs函数(单条件求和+多条件求和+模糊条件求和)
- 如何在Mac电脑上调整日期和时间?如何高效管理时间?
- 海尔计算机天越Y3的配置,海尔天越Y3S 拉近你与梦想的距离!
- vue中实现window.print()打印功能遇到的几个坑
- 十万火急的数据采集项目,爬虫代理测试对比
- 2021年中国茶叶电商发展现状及未来发展趋势分析[图]
- WORD 公式编辑工具
- python在视频上方加字_python 使用 MoviePy 给视频添加文字水印demo实现[附代码]