C#连接Kepserver OPC与PLC通讯程序源码教程

1.该教程是C#通过OPCDAAuto.dll连接Kepserver软件,可以实现与PLC和仪表等硬件通讯。该教程有两个程序,一个是测试程序,可以获取本机所有OPC服务器,连接断开指定的OPC服务器,获取服务器所有条目信息,对变量读写操作。

2.另一个程序是实际项目源码,连接西门子PLC,监控质量数据,存储数据到SQL数据库里,可以查询历史数据导出等功能。

3.该教程很适合学习,需要全套源码+V:1357448516或者+qq:584472557

 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OPCAutomation;

namespace OPCTest
{
    /// <summary>
    /// 名称:OPC Automation DA 2.0 测试
    /// 结果:本机OPC服务器测试成功
    /// 
    ///
    /// </summary>
    public partial class OPCTest : Form
    {        
        private OPCAutomation.OPCServer opcServer;//OPC server
        private OPCAutomation.OPCGroups opcGroups;//OPC groups
        private OPCAutomation.OPCGroup opcGroup;//OPC group
        private OPCAutomation.OPCItems opcItems;    //OPC items    
        private static int ClientHandle = 1;//客户端ID标识
        public OPCTest()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 枚举本地或远程计算机上的OPC服务(由于DCOM配置问题,远程尚未成功)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
             
                this.button3.Enabled = false;
                this.comboBox1.Items.Clear();
               // opcServer = new OPCServerClass();
                opcServer = new OPCServer();
                System.Net.IPHostEntry ipentry = new System.Net.IPHostEntry();
                ipentry = System.Net.Dns.GetHostEntry(textBox1.Text);
                string sname = System.Net.Dns.GetHostName();
                object serverList = opcServer.GetOPCServers(ipentry.HostName);
                foreach (string obj in (Array)serverList)
                {
                    this.comboBox1.Items.Add(obj);
                }
                if (this.comboBox1.Items.Count > 0)
                {
                    this.comboBox1.SelectedIndex = 0;
                    this.button1.Enabled = true;
                    this.button2.Enabled = true;
                }
            }
            catch (Exception se)
            {
                MessageBox.Show(se.Message);
                this.comboBox1.Items.Clear();
            }
            finally
            {
                this.button3.Enabled = true;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.button1.Enabled = false;
            this.button2.Enabled = false;
            this.button4.Enabled = false;
            this.dataGridView1.Rows.Clear();
        }
        /// <summary>
        /// 连接OPC服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                opcServer.Connect(this.comboBox1.Text, "");
                this.RecurBrowse(opcServer.CreateBrowser());
                if (!this.CreateGroup())
                {
                    return;
                }
                this.button4.Enabled = true;
            }
            catch (Exception se)
            {
                MessageBox.Show(se.Message); 
            }
        }
        /// <summary>
        /// 创建组,并加入数据交换事件
        /// </summary>
        /// <returns></returns>
        private bool CreateGroup()
        {
            try
            {
                this.opcGroups = opcServer.OPCGroups;
                this.opcGroup = opcGroups.Add("MyGroup");
                
                this.SetGroupProperty();//设置组属性
                opcGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(opcGroup_DataChange);
                opcGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(opcGroup_AsyncWriteComplete);                
                opcItems = opcGroup.OPCItems;
                return true;
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message);
                return false;
            }
            
        }
        /// <summary>
        /// 异步写数据完成时触 发的事件
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="Errors"></param>
        private void opcGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
        {
            this.l_ErrorsWrite.Text = "";
            for (int i = 1; i <= NumItems; i++)
            {
                this.l_ErrorsWrite.Text = "客户端ID:" + ClientHandles.GetValue(i).ToString() + "   错误:" + Errors.GetValue(i).ToString(); 
            }
        }
        /// <summary>
        /// 数据交换事件
        /// </summary>
        /// <param name="TransactionID">传输ID</param>
        /// <param name="NumItems">传输的ITEM数</param>
        /// <param name="ClientHandles">客户端标识</param>
        /// <param name="ItemValues">ITEM值</param>
        /// <param name="Qualities">品质</param>
        /// <param name="TimeStamps">时间戳</param>
        private void opcGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            try
            {
                textBox1.Text = NumItems.ToString();
                for (int i = 1; i <= NumItems; i++)
                {
                    //下面这种对应数据的方法是为了方便,有时候会出一些小错误。
                    int m = (int)ClientHandles.GetValue(i) - 1;
                    dataGridView1.Rows[m].Cells[1].Value = (TransactionID.ToString());
                    dataGridView1.Rows[m].Cells[2].Value = (ItemValues.GetValue(i).ToString());
                    dataGridView1.Rows[m].Cells[3].Value = (Qualities.GetValue(i).ToString());
                    dataGridView1.Rows[m].Cells[4].Value = (TimeStamps.GetValue(i).ToString());
                    dataGridView1.Rows[m].Cells[5].Value = ClientHandles.GetValue(i).ToString();
                }
            }
            catch (Exception ex)
            {
            
            }
        }
        /// <summary>
        /// 设置组属性
        /// </summary>
        /// <returns></returns>
        private bool SetGroupProperty()
        {
            try
            {
                opcServer.OPCGroups.DefaultGroupIsActive = Convert.ToBoolean(this.txtDGA.Text);
                opcServer.OPCGroups.DefaultGroupDeadband = (float)Convert.ToDouble(this.txtDGD.Text);
                opcGroup.IsActive = Convert.ToBoolean(txtActive.Text);
                opcGroup.UpdateRate = Convert.ToInt32(txtUpDate.Text);
                opcGroup.IsSubscribed = Convert.ToBoolean(txtSubscrib.Text);//如设置为false,则数据不更新
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return false;
            }
 
        }
        /// <summary>
        /// 获取节点
        /// </summary>
        /// <param name="opcBrowser"></param>
        private void RecurBrowse(OPCBrowser opcBrowser)
        {
            opcBrowser.ShowBranches();//展开分支            
            opcBrowser.ShowLeafs(true);//展开叶子节点
            foreach (object obj in opcBrowser)
            {
                this.listBox1.Items.Add(obj.ToString());//将获取的所有条目在列表中列示出来
            }
        }        
        /// <summary>
        /// 双击列表中的条目,将其路径
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.txtClientPath.Text = this.listBox1.SelectedItem.ToString();
        }
        /// <summary>
        /// 添加监视ITEM到表中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                OPCItem item1 = opcItems.AddItem(this.txtClientPath.Text, ClientHandle);
                this.dataGridView1.Rows.Add(new object[] { this.txtClientPath.Text.Split('.')[this.txtClientPath.Text.Split('.').Length -1], "", "", "", "", "", item1.ServerHandle.ToString() });
                this.txtClientName.Text = string.Empty;
                this.txtClientPath.Text = string.Empty;
                ClientHandle++;                
            }
            catch(Exception se)
            {
                MessageBox.Show(se.Message);
            }
        }
        /// <summary>
        /// 断开OPC连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (null != opcGroup)
            {
                opcGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(opcGroup_DataChange);
                opcGroup.AsyncWriteComplete -= new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(opcGroup_AsyncWriteComplete);
                opcGroup = null;
            }
            if (null != opcServer)
            {
                opcServer.Disconnect();                
                opcServer = null;                
                opcItems = null;
                this.comboBox1.Items.Clear();
                this.comboBox1.Text = string.Empty;
                this.button1.Enabled = false;
                this.button2.Enabled = false;
                this.listBox1.Items.Clear();
                this.button4.Enabled = false;
                this.dataGridView1.Rows.Clear();
                ClientHandle = 1;
                GC.Collect();
            }
        }
        /// <summary>
        /// 将新值写入选中的ITEM中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                OPCItem item = opcItems.GetOPCItem(Convert.ToInt32(this.dataGridView1.SelectedRows[0].Cells[6].Value));//根据OPC服务端ID获取新的OPCITEM
                //写多个数据时将相应的ARRAY对应即可
                //MessageBox.Show(this.dataGridView1.SelectedRows[0].Cells[6].Value.ToString());
                int[] ser = new int[]{0,item.ServerHandle};
                //MessageBox.Show(item.ServerHandle.ToString());
                Array serverHandles = (Array)ser;
                Array Errors;
                int TransactionID = 0;
                int cancelID;
                object[] value = new object[] { "", this.txtNewValue.Text }; //opc的数组是从1开始,所以这里0为空当
                Array Values = (Array)value;
                int ItemsNums = 1;//要写入数据的个数
                
                opcGroup.AsyncWrite(ItemsNums, ref serverHandles, ref Values, out Errors, TransactionID, out cancelID);
                this.checkBox1.Checked = false;
            }
            catch(Exception se)
            {
                MessageBox.Show(se.Message);
            }
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked)
            {
                if (this.dataGridView1.SelectedRows.Count > 0 && this.dataGridView1.SelectedRows[0].Cells[0].Value != null)
                {
                    this.txtCurrentValue.Text = this.dataGridView1.SelectedRows[0].Cells[2].Value.ToString();
                    this.txtNewValue.Enabled = true;
                    this.button5.Enabled = true;
                }
                else
                {
                    this.checkBox1.Checked = false;
                }
            }
            else
            {
                this.txtNewValue.Enabled = false;
                this.txtNewValue.Text = "";
                this.txtCurrentValue.Text = "";
                this.button5.Enabled = false;
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            this.SetGroupProperty();
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }       
    }
}

### C#汇川PLC通信的方法 为了实现C#应用程序汇川PLC之间的通信,可以采用基于Socket编程的方式或是利用现有的库来简化开发过程。对于后者而言,存在专门为这一目的设计的工具包,比如`PLCModbusTCPCommunicationLib`[^2]。 #### 使用ModbusTCP协议进行通信 当涉及到具体的协议时,ModbusTCP是一个常见的选择,在工业自动化领域广泛应用。此协议允许上位机通过简单的命令集访问连接到网络上的各种设备的数据寄存器。下面展示了一个基本的例子,说明如何创建一个能够发送请求并接收响应消息的服务端程序: ```csharp using System; using System.Net.Sockets; namespace PLCCommExample { public class ModbusClient : IDisposable { private TcpClient _client; /// <summary> /// 初始化一个新的客户端实例。 /// </summary> /// <param name="ipAddress">服务器IP地址。</param> /// <param name="port">服务器监听端口,默认为502。</param> public ModbusClient(string ipAddress, int port = 502){ _client = new TcpClient(ipAddress, port); } // 实现IDisposable接口... void IDisposable.Dispose(){ if (_client != null && _client.Connected) { _client.Close(); } } // 添加更多方法用于实际数据交互... } } ``` 这段代码片段展示了建立TCP连接的基础结构,并准备好了进一步扩展以执行特定于Modbus的操作。需要注意的是,这只是一个框架性的例子;要完成完整的解决方案还需要加入更多的逻辑处理,如构建和解析PDU(Protocol Data Unit),以及错误检测机制等[^1]。 #### 将通讯模块封装成类库 为了让上述功能更加易于集成和重用,建议将所有的通信相关代码打包进独立的.NET标准库项目中。这样做不仅提高了项目的维护性和灵活性,而且使得其他开发者也能轻松地将其纳入自己的工作中去。例如,可以在名为`PLCModbusTCPCommunicationLib`的命名空间下定义一系列静态或非静态成员函数,以便外部调用者可以根据需要灵活选用不同的API入口点。 #### 支持多种型号的PLC 考虑到不同类型的汇川PLC可能具有略微差异化的配置选项或者硬件特性,因此在编写通用型驱动程序的时候应该充分考虑兼容性问题。这意味着除了遵循统一的标准外,还需针对某些特殊情况进行额外的支持——无论是通过调整初始化参数还是增加新的指令集合[^3]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巍心1357448516

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值