VC环境下的OPC客户端程序开发
来源:岁月联盟
时间:2010-08-30
1 引言
随着通信技术、机技术和自动化技术的快速,大范围信息共享的需求在自动化系统中显得越来越来越重要,控制系统已逐渐发展成为以现场设备层、过程控制层和中央管理层三个层次组成的系统,因而对其开放性也提出了更高的要求。在传统的控制系统中,现场设备之间以及现场设备与控制软件之间的信息共享主要是通过驱动程序来实现的,不同厂家的设备使用不同的驱动程序,使得软件开发商不得不开发大量驱动程序来连接这些设备,即使设备厂家在硬件上做小小的改动,应用程序就可能重写,这也势必造成工业控制软硬件的升级与维护不便,给用户和软件开发商带来巨大的工作负担。同时,由于不同设备的驱动程序也有所不同,使得不同的应用程序也不能同时访问同一设备的数据,因此,需要制定一种统一开放的接口标准,使应用程序能够方便的存取一台或多台现场设备的数据,为不同厂商的软硬件提供一种系统集成和数据交换的途径。正是在自动化系统开放性要求的驱使下,促使了OPC技术的产生。2 OPC技术简介
OPC(OLE for Process Control)是基于微软公司的DNA(Distributed InterNet Application)构架和COM (Component Object Model)/DCOM(Distributed COM)技术,根据易扩展性而设计的,OPC规范定义了一个工业标准接口,这个标准使得COM技术适用于过程控制和制造自动化等应用领域。OLE最初意思为对象链接与嵌入,是微软的复合文档技术。随着后续版本OLE2中导入了COM技术之后,现在的OLE在原版的基础上增加了更多新的功能,包括结构化存储、统一数据传输和自动化等,它已经成为独立于计算机语言、操作系统甚至硬件平台的一种规范,进一步推广了面向对象程序设计的概念。OPC正是建立在OLE2规范之上,为工业控制领域提供了一种标准的数据访问机制。2.1 OPC数据访问规范
OPC规范是由世界主要的自动化设备制造商、OPC基金会和微软公司共同协商制定而成的,为不同厂商的设备和应用程序之间实现了接口标准化。它把硬件供应商和软件开发商分离开来,在设备、数据库等数据源和客户之间架起了一座桥梁,为解决统一接口标准问题提供了解决方案。这其中包括OPC数据访问规范(OPC DA)、OPC报警和事件规范(OPC AE)和OPC数据访问规范(OPC HDA)等,而OPC数据访问规范是最常用的规范之一。 通过对OPC数据访问规范的分析可知,在OPC数据访问规范中主要包括3类对象,分别是OPC Server、OPC Group和OPC Item。OPC服务器对象维护有关服务器的信息并作为OPC组对象的包容器,能够动态地创建和释放组对象;OPC组对象除了维护有关自身的信息之外,还提供了包容OPC项的机制,从逻辑上管理OPC项。它提供了客户组织数据的一种方法,客户可以对其进行读写,还可以设置客户端的数据更新速率。当服务器缓冲区内的数据发生改变时,OPC将向客户发出通知,客户得到通知后再进行必要处理,而无需浪费大量的时间进行查询;OPC项则表示了与OPC服务器的连接,它并不提供对外接口,客户端不能直接对其进行操作,而是通过组对象对其进行操作的。图1表示了这3类对象的相互关系以及它们与OPC客户端程序之间的关系。
2.2 OPC数据访问方式
OPC客户端在对OPC服务器进行数据访问时,可以选择两种不同的访问方式,即同步访问方式和异步访问方式。其中同步访问方式的实现相对简单,OPC服务器将OPC应用程序所要求得到的数据访问结果作为方法引数返回给OPC应用程序,此时OPC应用程序一直处于等待状态,直到结果被返回为止。当客户数目较少并且与服务器交互的数据量也较少的时候可以采用同步访问方式。与此相对,异步访问方式的实现较为复杂,OPC服务器接到OPC应用程序的要求后,立即将方法引数返回,OPC应用程序随后可以进行其它处理。当OPC服务器完成数据访问时,触发OPC应用程序的异步访问完成事件,将数据访问结果传送给OPC应用程序,OPC应用程序在VC的事件处理程序中接收从OPC服务器传来的数据。当有大量客户和大量数据交互时,异步访问方式的效率更高,能够避免客户数据请求的阻塞,从而最大限度的节省CPU和资源。图2和图3分别表示了两种数据访问方式的处理过程。

3 VC环境下OPC客户端程序设计
OPC客户端程序在设计时需要遵守OPC数据访问规范,实现规范所规定的全部必需接口。同时,客户端模块需要有独立的设备连接界面和监控运行界面,并能够支持多服务器的连接。下面详细介绍VC环境下的OPC客户端程序开发步骤,并给出关键源代码: (1)包含OPC头文件。首先创建新的工程,编辑StdAfx.h文件,加载opcda.h、opccomn.h、opcerrors.h、opcprops.h、opcquality.h以及opcda_i.c、opccomn_i.c文件。 (2)初始化COM库。由于OPC是基于COM技术制定的,所以在使用接口类之前必须首先使用CoInitialize(NULL)函数对COM库进行初始化,如果成功,函数返回值等于S_ OK。 HRESULT h1; h1=CoInitialize(NULL); if(h1!=S_OK) return(FAUSE); (3)通过OPC服务器的ProgID查询注册表中相关CLSID。每个COM服务器都有一个字符串型的ProgID,通过ProgID可以得到全球惟一的CLSID,使用CLSIDFromProgID( )函数实现ProgID到CLSID的转换。 h1=CLSIDFromProgID(ProgID,&CLSID); (4)连接OPC服务器,查询对象的IID_IOPCServer接口。在连接OPC服务器前,OPC客户端需要事先指定机名和OPC数据访问服务器名,建立连接后,创建OPC组并添加OPC数据项。 h1=CoCreateInstance(clsid,NULL,CLSCTX_ LOCAL_ SERVER,IID_IOPCServer,(void**)&m_OPCServer); (5)创建OPC组,查询IOPCItemMgt接口。IOPCServer接口的AddGroup()方法可以创建一个有指定名称和属性的OPC组。 h1=m_IOPCServer->AddGroup(L,” ”,TRUE,800,111,&TimeBias,&PercentDeadBand,LOCAL_ID,& m_ GrpSrvHandle,&RevisedUpdateRate,IID_IOPCItemMgt,(LPUNKNOWN*)m_IOPCItemMgt); (6)添加OPC数据项。使用IOPCItemMgt接口的AddItem()方法可以添加具有特殊属性的指定数量的数据项。 pOPCItemMgt->AddItems(ItemNumber,ItemArray,(OPCITEMRESULT**)&pItemResult,(HRESULT **) & pErrors); (7)OPC的数据项读写。对OPC数据项的读写可以有同步与异步之分,对于大量的数据传输,异步是更佳的选择,但对少量的数据传输,同步表现得更好。本程序采用异步访问方式,需要指向IOPCAsyncIO2指针。h1=m_IOPCItemMgt->QueryInterface(IID_IOPCAsyncIO2,(void**)&m_IOPCAsyncIO2);void CAsynOPCDlg::OnRead ( ) 实现异步读数据。h1=m_IOPCAsyncIO2->Read(1,phServer,1,&dwCancelID,&pErrors); delete[] phServer; void CAsynOPCDlg::OnWrite( ) 实现异步写数据。h1=m_IOPCAsyncIO2->Write(1,phServer,values,2,&dwCancelID,&pErrors); delete[] phServer; (8)OPC连接断开,释放接口指针。当程序退出或停止服务器时,依次删除Item(RemoveItems)、Group(RemoveGroups),释放资源。 void CAsynOPCDlg::OnStop( ) 停止服务器。h1=m_IOPCItemMgt->RemoveItems(1,phServer,&pErrors);删除Items。h1=m_IOPCServer->RemoveGroup(m_GrpSrvHandle,TRUE);删除Group。m_IOPCServer->Release( );释放服务器。m_IOPCServer=NULL;CoUninitialize( );关闭COM库。