求欧姆龙Fins协议动态链接库或者VC与欧姆龙Fins通讯例子。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求欧姆龙Fins协议动态链接库或者VC与欧姆龙Fins通讯例子。相关的知识,希望对你有一定的参考价值。

小弟正想学习上位机用VC与欧姆龙PLC做通信,希望哪位前辈有这方面的经验提供帮助,非常谢谢!

参考技术A 百度搜 FinsTCP.DLL ,支持双整形数据,浮点数据,直接引用即可; 参考技术B

VC不熟悉,提供一个C#的代码,谨供参考


using System.Collections.Generic;
using System;
using System.Linq;
using System.Drawing;
using System.Diagnostics;
using System.Data;
using System.Xml.Linq;
using Microsoft.VisualBasic;
using System.Collections;
using System.Windows.Forms;


using System.Net;
using System.Runtime.InteropServices;

namespace TCP_CLIENT

public partial class Form1

public Form1()

InitializeComponent();

    if (defaultInstance == null)
defaultInstance = this;


#region Default Instance

private static Form1 defaultInstance;


public static Form1 Default

get

if (defaultInstance == null)

defaultInstance = new Form1();
defaultInstance.FormClosed += new FormClosedEventHandler(defaultInstance_FormClosed);


return defaultInstance;

set

defaultInstance = value;



static void defaultInstance_FormClosed(object sender, FormClosedEventArgs e)

defaultInstance = null;


#endregion

        //定义一个新的FinsTcp对象,用到FinsTcp.DLL动态链接库
        FinsTcp.PlcClient PLC = new FinsTcp.PlcClient();
bool EntLink;//PLC连接状态标志
        Int32 PlcHand;//PLC连接句柄,对应不同的PLC,或者同一台PLC的不同连接

//窗体控件初始化
public void Form1_Load(System.Object sender, System.EventArgs e)

short i = 0;
this.CenterToScreen();
cmbReadMry.Items.Clear();
cmbReadMry.Items.Add("CIO");
cmbReadMry.Items.Add("WR");
cmbReadMry.Items.Add("DR");
cmbReadMry.Items.Add("ER");
            cmbReadMry.Items.Add("TIM");
            cmbReadMry.Items.Add("CNT");
cmbWriteMry.Items.Clear();
cmbWriteMry.Items.Add("CIO");
cmbWriteMry.Items.Add("WR");
cmbWriteMry.Items.Add("DR");
cmbWriteMry.Items.Add("ER");
            cmbWriteMry.Items.Add("TIM");
            cmbWriteMry.Items.Add("CNT");
cmbBitMry.Items.Clear();
cmbBitMry.Items.Add("CIO");
cmbBitMry.Items.Add("WR");
cmbBitMry.Items.Add("DR");
            cmbBitMry.Items.Add("ER");
cmbReadType.Items.Clear();
cmbReadType.Items.Add("INT16");
cmbReadType.Items.Add("UINT16");
cmbReadType.Items.Add("DINT32");
cmbReadType.Items.Add("HEX32");
cmbReadType.Items.Add("REAL32");
cmbReadType.Items.Add("BIN16");
            cmbReadType.Items.Add("BCD16");
            cmbReadType.Items.Add("BCD32");
cmbWriteType.Items.Clear();
cmbWriteType.Items.Add("INT16");
cmbWriteType.Items.Add("UINT16");
cmbWriteType.Items.Add("DINT32");
cmbWriteType.Items.Add("HEX32");
cmbWriteType.Items.Add("REAL32");
cmbWriteType.Items.Add("BIN16");
            cmbWriteType.Items.Add("BCD16");
            cmbWriteType.Items.Add("BCD32");
for (i = 0; i <= 15; i++)

cmbBit.Items.Add("Bit" + System.Convert.ToString(i));

cmbReadMry.SelectedIndex = 2;
cmbWriteMry.SelectedIndex = 2;
cmbBitMry.SelectedIndex = 0;
cmbBit.SelectedIndex = 0;
cmbReadType.SelectedIndex = 0;
cmbWriteType.SelectedIndex = 0;
lstRead.Items.Clear();
txtWrite.Text = "";



//建立与PLC的连接
public void butLink_Click(System.Object sender, System.EventArgs e)

short re = 0;
string restr = "";
            re = PLC.EntLink(txtLocalIP.Text.Trim(), Convert.ToUInt16(txtLocalPort.Text), txtRemoteIP.Text.Trim(), (Convert.ToUInt16(txtRemotePort.Text)),  "DEMO",ref PlcHand );
txtReLink.Text = re.ToString();
if (re == 0)

EntLink = true;
MessageBox.Show("PLC联接成功!");

else

EntLink = false;
MessageBox.Show("PLC联接失败: " + restr);


//断开与PLC的连接
public void butClose_Click(System.Object sender, System.EventArgs e)

short re = 0;
            EntLink = false;
re = PLC.DeLink(PlcHand );
txtReClose.Text = re.ToString();

//读取PLC 的数据
public void butRead_Click(System.Object sender, System.EventArgs e)

short i = 0;
            short re = 0;
object[] RD = null;
RD = new object[Convert.ToUInt16(txtReadCnt.Text)];
if (!EntLink)

MessageBox.Show("还未与PLC建立联接!");
return;

int var1 = cmbReadType.SelectedIndex + 1;
            FinsTcp.PlcClient.DataType typ = (FinsTcp.PlcClient.DataType)var1;
switch (cmbReadMry.SelectedIndex)

case 0:
                    re = PLC.CmdRead(PlcHand,FinsTcp.PlcClient.PlcMemory.CIO, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
break;
case 1:
                    re = PLC.CmdRead(PlcHand, FinsTcp.PlcClient.PlcMemory.WR, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
break;
case 2:
                    re = PLC.CmdRead(PlcHand, FinsTcp.PlcClient.PlcMemory.DR, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
break;
case 3:
                    re = PLC.CmdRead(PlcHand, FinsTcp.PlcClient.PlcMemory.ER, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
break;
                case 4:
                    re = PLC.CmdRead(PlcHand, FinsTcp.PlcClient.PlcMemory.TIM, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
                    break;
                case 5:
                    re = PLC.CmdRead(PlcHand, FinsTcp.PlcClient.PlcMemory.CNT, typ, Convert.ToUInt16(txtReadAdd.Text), Convert.ToUInt16(txtReadCnt.Text), ref RD);
                    break;

txtReRead.Text = re.ToString();
lstRead.Items.Clear();
for (i = 0; i < RD.Length; i++)

if (!(RD[i] == null))

lstRead.Items.Add(RD[i]);

else

lstRead.Items.Add("0");





//写入数据到PLC
public void butWrite_Click(System.Object sender, System.EventArgs e)

short i = 0;
            short re = 0;
string[] temp = null;
object[] WD = null;
if (!EntLink)

MessageBox.Show("还未与PLC建立联接!");
return;

WD = new object[Convert.ToUInt16(txtWriteCnt.Text)];
temp = txtWrite.Text.Split('\\n');
for (i = 0; i < WD.Length ; i++)

if (i >= temp.Length )

WD[i] = 0;

else

WD[i] = temp[i].Trim();


int var1 = cmbWriteType.SelectedIndex + 1;
            FinsTcp.PlcClient.DataType typ = (FinsTcp.PlcClient.DataType)var1;
switch (cmbWriteMry.SelectedIndex)

case 0:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.CIO, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
break;
case 1:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.WR, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
break;
case 2:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.DR, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
break;
case 3:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.ER, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
break;
                case 4:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.TIM, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
                    break;
                case 5:
                    re = PLC.CmdWrite(PlcHand, FinsTcp.PlcClient.PlcMemory.CNT, typ, Convert.ToUInt16(txtWriteAdd.Text), Convert.ToUInt16(txtWriteCnt.Text), ref WD);
                    break;

txtReWrite.Text = re.ToString();


//按位操作布尔量,读一个位
public void butBitTest_Click(System.Object sender, System.EventArgs e)

if (!EntLink)

MessageBox.Show("还未与PLC建立联接!");
return;

bool rd = false;
short re = 0;
switch (cmbBitMry.SelectedIndex)

case 0:
                    re = PLC.Bit_Test(PlcHand, FinsTcp.PlcClient.PlcMemory.CIO, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex), ref rd);
break;
case 1:
                    re = PLC.Bit_Test(PlcHand, FinsTcp.PlcClient.PlcMemory.WR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex), ref rd);
break;
case 2:
                    re = PLC.Bit_Test(PlcHand, FinsTcp.PlcClient.PlcMemory.DR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex), ref rd);
break;
                case 3:
                    re = PLC.Bit_Test(PlcHand, FinsTcp.PlcClient.PlcMemory.ER, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex), ref rd);
                    break;

txtBitTest.Text = rd.ToString();
txtReBit.Text = re.ToString();

//按位操作布尔量,设置一个位位1
public void butBitSet_Click(System.Object sender, System.EventArgs e)

if (!EntLink)

MessageBox.Show("还未与PLC建立联接!");
return;

short re = 0;
switch (cmbBitMry.SelectedIndex)

case 0:
                    re = PLC.Bit_Set(PlcHand, FinsTcp.PlcClient.PlcMemory.CIO, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
case 1:
                    re = PLC.Bit_Set(PlcHand, FinsTcp.PlcClient.PlcMemory.WR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
case 2:
                    re = PLC.Bit_Set(PlcHand, FinsTcp.PlcClient.PlcMemory.DR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
                case 3:
                    re = PLC.Bit_Set(PlcHand, FinsTcp.PlcClient.PlcMemory.ER, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
                    break;

txtReBit.Text = re.ToString();

//按位操作布尔量,设置一个位为0
public void butBitRst_Click(System.Object sender, System.EventArgs e)

if (!EntLink)

MessageBox.Show("还未与PLC建立联接!");
return;

short re = 0;
switch (cmbBitMry.SelectedIndex)

case 0:
                    re = PLC.Bit_Reset(PlcHand, FinsTcp.PlcClient.PlcMemory.CIO, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
case 1:
                    re = PLC.Bit_Reset(PlcHand, FinsTcp.PlcClient.PlcMemory.WR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
case 2:
                    re = PLC.Bit_Reset(PlcHand, FinsTcp.PlcClient.PlcMemory.DR, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
break;
                case 3:
                    re = PLC.Bit_Reset(PlcHand, FinsTcp.PlcClient.PlcMemory.ER, Convert.ToUInt16(txtBitAdd.Text), Convert.ToUInt16(cmbBit.SelectedIndex));
                    break;

txtReBit.Text = re.ToString();





参考技术C 欧姆龙的FINS 协议文档,有详细的说明

使用C#实现欧姆龙PLC FINS协议读取

由于采用欧姆龙的PLC进行设计和开发,所以需要与它进行协议通讯。

之前也有同事写过这样的协议,但是使用起来不是很方便,因此重新写了一份FINS协议,在开发的过程中,也碰到一些问题,比如C#结构体对齐问题,导致发送数据不对,后来仔细检查才解决了这个问题。

又由于对欧姆龙的PLC区域不是很了解,一直不了解读写位和读写字的区别,后来经过反复验证,才发现读写位与字的区别是在于区域码会不一样,也就是说,即使是同一个区,也是分为两个区码,比如W区,按位读写就是0x31, 按字读写就是0xB1,其它发送的字节是一样,仅这里的区别。

另外PLC里的字都是网络顺序,因此要记得转换为小端格式,才能准确地读取值。

同时,在这里也使用了动态地构造数据包的方式,与固定填写有点区别,这个可以参考之前使用BufferStream的文章。

在位与字的区分,就写了下面的代码:

 private byte GetAreaTypeFlag(OmronAddressType omronAddressType, bool isBitProcess)
        
            if (isBitProcess)
            
                //位处理
                switch (omronAddressType)
                
                    case OmronAddressType.CIO:
                        return 0x30;
                    case OmronAddressType.WR:
                   

以上是关于求欧姆龙Fins协议动态链接库或者VC与欧姆龙Fins通讯例子。的主要内容,如果未能解决你的问题,请参考以下文章

使用C#实现欧姆龙PLC FINS协议读取

使用C#实现欧姆龙PLC FINS协议读取

使用C#实现欧姆龙PLC FINS协议读取

欧姆龙的PLC的FINS通讯协议的C例子

欧姆龙OMRON PLC之HostLink通讯协议-FINS命令工作模式篇

欧姆龙OMRON PLC之HostLink通讯协议-FINS命令工作模式篇