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)相关推荐

  1. C#上位机和松下PLC通讯

    C#上位机和松下PLC通讯 1.前言 也好久没回来看博客了,看大家对于其他的PLC的需求都是有的,说明搞我们工业控制这一行的人也是很多的.刚好最近基于项目需要,一些新的东西,需要和松下PLC的FP系列 ...

  2. wincc上位机与1200组态步骤_组态上位机WINCC与PLC通讯连接

    WINCC 与 PLC 通讯连接 1 . STEP 7 硬件组态 STEP7 设置 MPI 通讯, 2 .安装 CP5611 通讯板卡 3 .添加驱动程序和系统参数设置 打开 WINCC 工程在 Ta ...

  3. 上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,

    上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通讯,, ...

  4. 上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯

    上位机与PLC 通讯源码 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通讯,, ...

  5. 上位机与PLC 通讯源码DEMO 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制

    上位机与PLC 通讯源码DEMO 上位机与三菱PLC,西门子PLC通讯 同时一起通讯,单独控制,三菱采用官方MX 通讯,支持三菱FX系列,A系列,Q系列,L系列,R系列,全系系列,各种串口和各种网口通 ...

  6. PLC通讯实现-C#实现欧姆龙以太网通讯FINS(二)

    PLC通讯实现-C#实现欧姆龙以太网通讯FINS(二) 背景 抽象设计 欧姆龙以太网通讯实现FINS 背景 本人近十年的工作都与工业软件相关.其中工控系统开发过程中有一个必要环节就是跟各大厂商的PLC ...

  7. 【无标题】C#上位机与三菱PLC FX2NC通讯方法

    *** C#上位机与三菱PLC FX2NC通讯方法*** 第一步从官网中下载MX COMPONENT并安装好; 第二步从安装好的MX COMPONENT路径中找到"Samples" ...

  8. 欧姆龙plc通讯协议格式

    欧姆龙CPM1A型plc与上位计算机通信的顺序是上位机先发出命令信息给PLC,PLC返回响应信息给上位 机.每次通信发送/接受的一组数据称为一"帧".帧由少于131个字符的数据构成 ...

  9. 欧姆龙 PLC通讯协议

    https://blog.csdn.net/sgmcumt/article/details/87435778 fins 欧姆龙 PLC通讯协议

  10. 安川与欧姆龙Plc通讯设置方法

    安川与欧姆龙Plc通讯设置方法 id=609745949439&

最新文章

  1. go语言实现简易ftp客户端
  2. 王石:人生60岁才是开始
  3. “供应链”之后,传统零售如何会战“服务链”?
  4. showModalDialog和showModelessDialog缓存问题,参数详解,
  5. 全卷积网络FCN详解
  6. tomcat下只有.class文件 没有java文件_解决tomcat发布工程后,WEB-INF/classes下文件不编译的问题...
  7. 【转】 Android 屏幕切换总结
  8. vue从url中获取token并加入到 请求头里_BATJ都会用到的接口鉴权cookie、session 和token...
  9. LeetCode 392. 判断子序列(双指针二分查找)
  10. apache httpd配置后启动失败或域名绑定无效等问题解决方法
  11. python n个list如何组成矩阵_python和c++通信示例
  12. java左移负数位_java的左移运算符和右移运算符
  13. 2021年影响会计人员的十大信息技术榜单出炉,RPA再次登榜
  14. 模拟淘宝侧边服务模块鼠标悬停效果的三种实现方式总结
  15. 黑马程序员入学Java知识——精华总结
  16. html中怎么把h标签左移,基础标签--h、p、a、hr、br、img、base
  17. php中.=是什么意思,javascript中$符号是什么意思?
  18. php解析json转数组,php json转数组出错
  19. 腾讯音乐(K歌)的粗排模型
  20. Cerea学习,包含示例代码

热门文章

  1. b和kb的换算_b和kb的换算(b换算成kb)
  2. 一文带你由浅入深Netty异步非阻塞世界
  3. excel学习-sumifs函数(单条件求和+多条件求和+模糊条件求和)
  4. 如何在Mac电脑上调整日期和时间?如何高效管理时间?
  5. 海尔计算机天越Y3的配置,海尔天越Y3S 拉近你与梦想的距离!
  6. vue中实现window.print()打印功能遇到的几个坑
  7. 十万火急的数据采集项目,爬虫代理测试对比
  8. 2021年中国茶叶电商发展现状及未来发展趋势分析[图]
  9. WORD 公式编辑工具
  10. python在视频上方加字_python 使用 MoviePy 给视频添加文字水印demo实现[附代码]