OPC技术的上位机与PLC之间的通信现代工业控制系统通常以PC机为上位机_第1页
OPC技术的上位机与PLC之间的通信现代工业控制系统通常以PC机为上位机_第2页
OPC技术的上位机与PLC之间的通信现代工业控制系统通常以PC机为上位机_第3页
OPC技术的上位机与PLC之间的通信现代工业控制系统通常以PC机为上位机_第4页
OPC技术的上位机与PLC之间的通信现代工业控制系统通常以PC机为上位机_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

OPCHYPERLINK”http://www.jdzyjs.com”技术的上位机与PLC之间的HYPERLINK"http://www.jdzyjs.com"通信现代工业掌握系统通常以PC机为上位机,通过与现场工控设备如PLC的HYPERLINK"http://www.jdzyjs。com"数据交换与处理,实现对生产过程的自动掌握。对于小型掌握系统,采纳专门的组态软件成本太高,用VB设计监控系统则可以降低成本,但首先要解决上位机与PLC之间HYPERLINK"http://www.jdzyjs.com"通信问题。以往使用较多的进程间HYPERLINK"http://www。jdzyjs.com"通信方式是DDE(动态HYPERLINK"http://www.jdzyjs。com"数据交换)方式,随着OPCHYPERLINK"http://www.jdzyjs。com"技术的进展和普及,它已成为工业过程掌握的HYPERLINK”http://www。jdzyjs。com"通信标准。OPC服务器有两类接口,其中自动化接口主要用于VB、Delphi等开发工具。本文利用罗克韦尔公司供应的OPC接口,用VB编写了客户端应用程序,实现了上位机与AB可编程掌握器之间的HYPERLINK"http://www.jdzyjs.com”数据交换。2

OPCHYPERLINK"http://www.jdzyjs.com”技术简介ﻫOPC(OLEforProcessControl—用于过程掌握的对象连接与嵌入)是一套以微软对象连接与嵌入OLE、组件对象模型COM、分布式组件对象模型DCOM(DistributedCOM)HYPERLINK"http://www.jdzyjs。com"技术为基础,HYPERLINK”http://www.jdzyjs.com"基于Windows操作平台,为工业应用程序之间供应高效的信息集成和交互功能的组件对象模型接口标准。OPC实际上是供应了一种机制,通过这种机制,系统能够以服务器/客户端标准方式从服务器猎取HYPERLINK"http://www。jdzyjs。com"数据并将其传递给任何客户应用程序。这样,只要生产商开发一套遵循OPC规范的服务器与HYPERLINK"http://www.jdzyjs.com"数据进行HYPERLINK"http://www.jdzyjs。com"通信,其他任何客户应用程序便能通过服务器访问设备。ﻫOPC服务器有两类接口:定制接口和自动化接口。定制接口为C++程序服务,自动化接口为VB这一类可使用自动化对象的程序服务.定制接口是服务商必须供应的,而自动化接口则是可选的,不过OPC基金会供应了一个叫做“自动化包装器”的动态连接库,用于在两者间转换.ﻫOPCHYPERLINK”http://www.jdzyjs。com”数据存取规范规定的基本对象有三类:服务器(server)、组(group)和HYPERLINK”http://www.jdzyjs.com"数据项(item)。服务器对象包含服务器的全部信息,也是组对象的容器,一个服务器对应于一个OPCserver,即一种设备的驱动程序。组对象除了包含它自身信息外,还负责管理HYPERLINK"http://www.jdzyj”数据项。每一个HYPERLINK”http://www。jdzyjs.com"数据项代表到HYPERLINK”http://www。jdzyjs.com"数据源的一个连接,但它没有供应外部接口,客户端程序无法对HYPERLINK"http://www。jdzyjs.com”数据项直接进行操作,应用程序必须依靠HYPERLINK"http://www.jdzyjs.com”数据项的容器组对象来对它进行操作。3

HYPERLINK"http://www.jdzyjs。com"通信实现ﻫ3.1

RSLinx的配置

RSLinx是AB可编程掌握器在Windows环境下建立工厂所用HYPERLINK"http://www。jdzyjs.com"通信方案的工具,它不仅供应了多种网络驱动程序,而且供应了最快速的OPC、DDE和CustomC/C++接口.本设计中上位机与Logix5550掌握器采纳RS—232串口方式连接,在RSLinx中要对DF1网络驱动程序组态,设置串口特性:COM1、波特率19200bps、一个停止位、无奇偶校验、全双工、BCC校验码。此外要使用RSLinx的OPC接口作为服务器,还要在RSLinx中对OPC进行配置。ﻫ3.2

安装OPC自动化接口服务ﻫ若要用VB开发OPC应用程序,必须安装OPC自动化接口服务,保证计算机系统名目下有OPCDAAuto。dll。OPC基金会供应了一个叫做“自动化包装器”的动态连接库,从OPC基金会的网站(HYPERLINK"http://www.opcfoundation.org/"www.opcfoundation.org)可下载。在VB环境中,按“工程"的子菜单“引用…”后,弹出对话框,选择其中的“RSLinxOPCAutomation2.0”项,这样才能使用自动化接口。ﻫ3.3

程序设计ﻫ用VB编写了OPC客户端应用程序,实现了上位机与Logix5550掌握器之间的HYPERLINK”http://www。jdzyjs.com"通信.主要程序代码如下:ﻫ(1)连接OPC服务器

DimWithEventsMyOPCServerAsOPCServer

‘定义服务器对象变量MyOPCServer

DimWithEventsMyOPCGroupAsOPCGroup

‘定义OPC组对象变量MyOPCGroup

SetMyOPCServer=NewOPCServer

MyOPCServer。Connect”RSLinxOPCServer"‘连接RSLinx的OPC服务器ﻫ(2)添加OPC组对象ﻫSetMyOPCGroup=MyOPCServer.OPCGroups。Add("Group1")

‘添加OPC组对象MyOPCGroup.IsSubscribed=True

‘设置该组HYPERLINK"http://www.jdzyjs.com”数据为后台刷新

MyOPCGroup。IsActive=True

ﻫ‘设置该组为激活状态MyOPCGroup.UpdateRate=1000

ﻫ‘设置HYPERLINK”http://www.jdzyjs。com"数据刷新时间为1000ﻫ(3)添加HYPERLINK"http://www。jdzyjs.com”数据项ﻫDimabItemIDs()AsString

ﻫ‘项标识符ﻫDimabClientHandles()AsLong

ﻫ‘客户端句柄ﻫDimabServerHandles()AsLongﻫ‘服务器端句柄

DimabErrors()AsLong

ﻫDimiAsLongﻫItemCount=5

DimoOPCItemAsRSLinxOPCAutomation.OPCItemﻫFori=1To5ﻫabItemIDs(i)=”[”&txtTopic&"]"&txtItem(i)

‘将Topic名和标签名赋给项标识符ﻫabClientHandles(i)=i

ﻫ‘给客户端句柄赋值

Nexti

MyOPCGroup。OPCItems。AddItemsItemCount,abItemIDs,abClientHandles,abServerHandles,abErrors

‘添加HYPERLINK"http://www。jdzyjs.com"数据项操作

(4)同步HYPERLINK"http://www.jdzyjs.com"数据读写

OPCHYPERLINK"http://www.jdzyjs.com”数据存取有同步方式和异步方式两种。异步读写HYPERLINK"http://www.jdzyjs.com"数据简洁,需要与大事结合使用,与同步相比速度慢但精准性高.同步读写HYPERLINK”http://www.jdzyjs.com”数据简洁,直接使用OPCItem的方法即可。ﻫDimOneAsOPCItemﻫDimIndexAsLong

ﻫ‘Index为标签挨次号ﻫDimOneReadAsString

DimXieAsString

ﻫSetOne=MyOPCGroup.OPCItems(Index)ﻫOne。ReadOPCCacheﻫOneRead=One.Value

ﻫ‘读HYPERLINK"http://www.jdzyjs。com”数据ﻫOne.Write(Xie)

ﻫ‘写HYPERLINK"http://www。jdzyjs.com"数据ﻫ若只读取HYPERLINK”http://www.jdzyjs.com”数据,可以使用DataChange大事,当掌握器中所要访问的HYPERLINK”http://www.jdzyjs。com"数据一旦发生转变时将会触发该大事,并将该HYPERLINK"http://www.jdzyjs.com"数据自动读到TxtValue文本框。ﻫPrivateSubMyOPCGroup_DataChange(ByValTransactionIDAsLong,ByValNumItemsAsLong,ClientHandles()AsLong,ItemValues()AsVariant,Qualities()AsLong,TimeStamps()AsDate)ﻫ‘自动刷新HYPERLINK”http://www。jdzyjs.com”数据ﻫDimiAsLongﻫFori=1ToNumItemsﻫtxtValue(ClientHandles(i))=ItemValues(i)

ﻫ‘猎取项的值ﻫtxtTime(ClientHandles(i))=TimeStamps(i)

ﻫ‘猎取项的时间戳ﻫtxtQuantity(ClientHandles(i))=GetQualityString(Qualities(i))

‘猎取项的品质ﻫNexti

EndSub

(5)断开OPC服务器

MyOPCServer.OPCGroups.RemoveAll

‘移除全部OPCGroup,空出资源ﻫSetMyOPCGroup=Nothing

ﻫMyOPCServer。Disconnect

ﻫ‘断开连接

4

结束语ﻫ利用本文介绍的方法,在实验室实现了上位机和PLC之间的HYPERLINK"http://www.jdzyjs。com"通信,图1是OPC客户端设置界面。此外我们还设计了城市供水监控系统,鉴于篇幅,监控界面不再一一列出。在上一次发表的HYPERLINK”http://www.gongkong.com/exhibit/lunwen/paper_detail.asp?id=1594"\t"_blank”<运用VC#编程通过OPC方式实现PC机与西门子PLC通讯>主要讲的是同步通讯,本文将主要讲解如何编程实现异步通讯,通过讲解你也将会知道同步通讯与异步通讯的区分,以及在什么情况下使用异步通讯。ﻫﻫ1、配置OPC服务器ﻫ对于服务器的配置与同步通讯的配置一样,这里不需再讲解,若有不清楚的,可以参阅之前发布的<运用VC#编程通过OPC方式实现PC机与西门子PLC通讯〉

ﻫ2、OPC编程ﻫ变量组、项的命名规章与同步通讯的一样,这里不再描叙,下面主要就开发一个异步通讯类AsynServer来讲解如何编程.

ﻫ〈1>、引用ﻫ在VC#开发环境中添加对OpcRcw.Da库以及OpcRcw.Comn库的引用,该库属于.NET库,不属于COM库,西门子虽然编写了类库,以提供对.NET平台的支持,但这些类库仍然难于编程,里面包含了大量的在托管和非托管区传输数据,因此我们需要在它的基础上再开发一个类库,以简化以后的编程,首先在类的开头使用命名空间:ﻫusingOpcRcw。Comn;

usingOpcRcw.Da;

usingSystem。Runtime.InteropServices;

usingSystem.Collections;ﻫﻫ〈2〉、编程ﻫ异步编程的原理就是在OPC服务器那边检测当前活动的变量组,一但检测到某一个变量,譬如变量Q0.0从1变成0,就会执行一个回调函数,以实现针对变量发生变化时需要实现的动作,在这里可以采纳委托来实现该功能。ﻫﻫ1、在命名空间的内部、类AsynServer声明之前添加委托的申明:ﻫ//定义用于返回发生变化的项的值和其对应的客户句柄ﻫpublicdelegatevoidDataChange(object[]values,int[]itemsID);ﻫ

2、该类继承于西门子供应的库接口IOPCDataCallbackﻫpublicclassAsynServer:IOPCDataCallbackﻫ在类的开头部分声明变量:ﻫstructgroupStruﻫ{ﻫpublicintgroupID;

publicobjectgroupObj;ﻫ}ﻫinternalconstintLOCALE_ID=0x407;//本地语言

privateGuidiidRequiredInterface;ﻫprivatestringserverType=””;ﻫprivateinthClientGroup=0;//客户组号ﻫprivateintnSvrGroupID;//servergrouphandlefortheaddedgroupﻫprivateHashtablehashGroup;//用于把组收集到一起ﻫprivateinthClientItem=0;//Item号

3、编写构造函数,接收委托参数已确定当数据发生变化时需要执行的方法入口点:ﻫ//创建服务器ﻫ//svrType服务器类型的枚举ﻫ//dataChange供应用于在数据发生变化时需要执行的函数入口ﻫpublicAsynServer(ServerTypesvrType,DataChangedataChange)ﻫ{ﻫswitch(svrType)

{

caseServerType。OPC_SimaticHMI_PTPRO:ﻫserverType="OPC.SimaticHMI。PTPro";break;ﻫcaseServerType。OPC_SimaticNET:ﻫserverType="OPC.SimaticNET";break;

caseServerType.OPC_SimaticNET_DP:ﻫserverType="OPC.SimaticNET.DP";break;

caseServerType。OPC_SimaticNET_PD:ﻫserverType=”OPC.SimaticNET.PD”;break;ﻫcaseServerType。OPCServer_WinCC:

serverType=”OPCServer。WinCC";break;ﻫﻫ}ﻫhashGroup=newHashtable(11);ﻫdtChange=dataChange;ﻫ}ﻫﻫ4、创建服务器ﻫ//创建一个OPCServer接口ﻫ//error返回错误信息ﻫ//若为true,创建成功,否则创建失败ﻫpublicboolOpen(outstringerror)ﻫ{

error="";boolsuccess=true;ﻫTypesvrComponenttyp;ﻫ//猎取OPCServerCOM接口

iidRequiredInterface=typeof(IOPCItemMgt).GUID;

svrComponenttyp=System.Type。GetTypeFromProgID(serverType);ﻫtry

{ﻫ//创建接口ﻫpIOPCServer=(IOPCServer)System.Activator。CreateInstance(svrComponenttyp);ﻫerror="”;ﻫ}ﻫcatch(System。Exceptionerr)//捕获失败信息ﻫ{

error="错误信息:”+err.Message;success=false;

}

returnsuccess;ﻫ}ﻫﻫ5、编写添加Group的函数

///

///添加组

///

///组名

////创建时,组是否被激活ﻫ/////组的刷新频率,以ms为单位ﻫ///返回错误信息

///若为true,添加成功,否则添加失败ﻫpublicboolAddGroup(stringgroupName,intbActive,intupdateRate,outstringerror)ﻫ{

error=””;boolsuccess=true;ﻫintdwLCID=0x407;//本地语言为英语ﻫintpRevUpdateRate;ﻫfloatdeadband=0;ﻫ//处理非托管COM内存ﻫGCHandlehDeadband;ﻫIntPtrpTimeBias=IntPtr.Zero;ﻫhDeadband=GCHandle.Alloc(deadband,GCHandleType.Pinned);ﻫtry

{ﻫpIOPCServer。AddGroup(groupName,//组名ﻫbActive,//创建时,组是否被激活ﻫupdateRate,//组的刷新频率,以ms为单位ﻫhClientGroup,//客户号ﻫpTimeBias,//这里不使用ﻫ(IntPtr)hDeadband,

dwLCID,//本地语言ﻫoutnSvrGroupID,//移去组时,用到的组ID号ﻫoutpRevUpdateRate,//返回组中的变量转变时的最短通知时间间隔ﻫrefiidRequiredInterface,ﻫoutpobjGroup1);//指向要求的接口ﻫhClientGroup=hClientGroup+1;

groupStrugrp=newgroupStru();ﻫgrp。groupID=nSvrGroupID;grp.groupObj=pobjGroup1;ﻫthis.hashGroup.Add(groupName,grp);//储存组信息ﻫ//对异步操作设置回调,初始化接口ﻫpIConnectionPointContainer=(IConnectionPointContainer)pobjGroup1;ﻫGuidiid=typeof(IOPCDataCallback).GUID;

pIConnectionPointContainer。FindConnectionPoint(refiid,outpIConnectionPoint);

pIConnectionPoint.Advise(this,outdwCookie);

}ﻫcatch(System.Exceptionerr)//捕获失败信息

{ﻫerror=”错误信息:”+err.Message;success=false;

finallyﻫ{ﻫif(hDeadband.IsAllocated)hDeadband.Free();ﻫ}ﻫreturnsuccess;ﻫ}ﻫ

6、编写激活、或者取消激活组的函数ﻫﻫ在同步编程中对于组的激活或者取消激活没有实质的意义,但在异步通讯编程中却特别重要,这是由于OPC服务器只对当前处于活动状态的组中的变量进行监控,同时这也是很有必要的,由于我们可以把不同界面中的变量编程不同的组,即同一界面中的变量规成一个组,而在某一时刻供应应用户的只有一个界面,让该界面中用到的组处于活动状态,这样执行委托调用时只会执行于该界面中有关的变量检测,而如果让全部的组处于活动状态,则当前没有显示给用户的界面用到的变量若发生变化也会触发对委托函数的调用,这根本是没有必要的,同时会大大降低程序的性能,请严格掌握组的激活。ﻫ///

///激活或者取消激活组ﻫ///

///指定组名ﻫ///true为激活,false为取消激活

///若有错误,返回错误信息ﻫ///若为true,添加成功,否则添加失败

publicboolAciveGroup(stringgroupName,booltoActive,outstringerror)ﻫ{ﻫerror="";boolsuccess=true;

//通过名称猎取组ﻫobjectgrp=((groupStru)hashGroup[groupName])。groupObj;ﻫIOPCGroupStateMgtgroupStateMgt=(IOPCGroupStateMgt)grp;

//初始化传递参数ﻫIntPtrpRequestedUpdateRate=IntPtr.Zero;//由客户指定的Item更新间隔时间ﻫintnRevUpdateRate=0;//由服务器返回的能够更新的最短时间间隔

IntPtrhClientGroup=IntPtr.Zero;//客户组ﻫIntPtrpTimeBias=IntPtr.Zero;ﻫIntPtrpDeadband=IntPtr。Zero;ﻫIntPtrpLCID=IntPtr。Zero;

ﻫ//激活或者取消激活组ﻫintnActive=0;ﻫGCHandlehActive=GCHandle.Alloc(nActive,GCHandleType。Pinned);ﻫif(toActive)ﻫhActive。Target=1;ﻫelseﻫhActive。Target=0;ﻫtryﻫ{ﻫgroupStateMgt.SetState(pRequestedUpdateRate,outnRevUpdateRate,hActive。AddrOfPinnedObject(),pTimeBias,pDeadband,pLCID,hClientGroup);ﻫ}ﻫcatch(System.Exceptionerr)ﻫ{ﻫerror="错误信息:"+err。Message;success=false;ﻫ}

finallyﻫ{ﻫhActive。Free();ﻫ}ﻫreturnsuccess;ﻫ}

ﻫ7、向指定的组中添加变量的函数ﻫ///ﻫ///向指定的组添加一系列项

///ﻫ///指定组名ﻫ///完整的item名数组

///由服务器返回读写数据时需要使用的item号

///无错误,返回true,否则返回falseﻫpublicboolAddItems(stringgroupName,string[]itemsName,int[]itemsID)ﻫ{

boolsuccess=true;

OPCITEMDEF[]ItemDefArray=newOPCITEMDEF[itemsName。Length];

for(inti=0;i

{ﻫhClientItem=hClientItem+1;//客户项自动加1ﻫItemDefArray[i].szAccessPath=”";//可选的通道路径,对于SimatiicNet不需要。ﻫItemDefArray[i].szItemID=itemsName[i];//ItemID,seeaboveﻫItemDefArray[i]。bActive=1;//itemisactive

ItemDefArray[i].hClient=hClientItem;//clienthandle,在OnDataChange中会用到ﻫItemDefArray[i].dwBlobSize=0;//blobsize

ItemDefArray[i].pBlob=IntPtr。Zero;//pointertoblobﻫItemDefArray[i].vtRequestedDataType=4;//DWord数据类型

//初始化输出参数ﻫIntPtrpResults=IntPtr.Zero;ﻫIntPtrpErrors=IntPtr.Zero;ﻫtryﻫ{ﻫ//添加项到组ﻫobjectgrp=((groupStru)hashGroup[groupName]).groupObj;

((IOPCItemMgt)grp)。AddItems(itemsName.Length,ItemDefArray,outpResults,outpErrors);ﻫﻫint[]errors=newint[itemsName。Length];ﻫIntPtrpos=pResults;ﻫMarshal.Copy(pErrors,errors,0,itemsName.Length);

for(inti=0;iﻫ{ﻫif(errors[i]==0)ﻫ{ﻫOPCITEMRESULTresult=(OPCITEMRESULT)Marshal.PtrToStructure(pos,typeof(OPCITEMRESULT));ﻫitemsID[i]=result。hServer;ﻫpos=newIntPtr(pos.ToInt32()+Marshal.SizeOf(typeof(OPCITEMRESULT)));ﻫ}ﻫelseﻫ{ﻫStringpstrError;ﻫpIOPCServer。GetErrorString(errors[0],0x407,outpstrError);ﻫsuccess=false;ﻫbreak;ﻫ}

}ﻫSetItenClient(groupName,itemsID,itemsID);//要求始终只有一个组被激活,才不会引起冲突。ﻫ}ﻫcatch(System.Exceptionerr)//catchforerrorinaddingitems。ﻫ{ﻫsuccess=false;ﻫ//error=”错误信息:"+error+err。Message;ﻫ}ﻫfinallyﻫ{

//释放非托管内存ﻫif(pResults!=IntPtr.Zero)ﻫ{

Marshal.FreeCoTaskMem(pResults);ﻫpResults=IntPtr.Zero;ﻫ}

if(pErrors!=IntPtr.Zero)ﻫ{ﻫMarshal.FreeCoTaskMem(pErrors);

pErrors=IntPtr。Zero;ﻫ}ﻫ}ﻫreturnsuccess;ﻫ}

说明:使用该函数时,在类的开头,应该先声明整数数据,以用于保存由本函数返回的服务器对每一项安排的ItemID号:ﻫﻫ8、下面编写的是一个最重要的重载函数,当检测到当前活动组中的某个变量发生变化时,就会调用委托。

ﻫ//数据变化时处理的问题ﻫpublicvirtualvoidOnDataChange(Int32dwTransid,ﻫInt32hGroup,

Int32hrMasterquality,ﻫInt32hrMastererror,ﻫInt32dwCount,

int[]phClientItems,

object[]pvValues,ﻫshort[]pwQualities,ﻫOpcRcw。Da。FILETIME[]pftTimeStamps,ﻫint[]pErrors)

{ﻫdtChange(pvValues,phClientItems);ﻫﻫ}ﻫ该函数的代码只有一句,即调用委托函数。ﻫ以上编写的是需要实现监控的最重要的方法,当然不完善,还有很多方法和重载函数可以编写,这里就不简略介绍.ﻫ

9、编写基本的测试程序,用于检测上面编写的异步类AsynServerﻫ

<1〉、重新创建一个工程,添加对上面编写的异步类的引用,并在类的开头部分添加变量声明:ﻫ//声明委托ﻫprivateS7Connection.DataChangedt;ﻫ//声明服务器ﻫS7Connection.AsynServerserver;

ﻫ<2〉、初始化服务器数据ﻫdt=newS7Connection.DataChange(DataChange);ﻫserver=newAsynServer(S7Connection.ServerType。OPC_SimaticNET,dt);

stringerr;ﻫserver.Open(outerr);ﻫserver.AddGroup("maiker”,1,300,outerr);ﻫserver。AddItems(”maiker",m1,nt1);ﻫserver。AddGroup(”maiker1",1,300,outerr);ﻫserver.AddItems(”maiker1",m2,nt2);ﻫnt[0]=nt1[0];nt[1]=nt1[1];ﻫ

<3>、添加两个单选按钮,用于选择某个组,并编写相应的程序ﻫstringerr,err1;ﻫif(server==null)return;ﻫif(radioButton1.Checked)

{nt[0]=nt1[0];nt[1]=nt1[1];ﻫserver.AciveGroup("maiker",true,outerr);ﻫserver。AciveGroup("maiker1",false,outerr1);ﻫﻫ}ﻫelse

{ﻫnt[0]=nt2[0];nt[1]=nt2[1];ﻫserver.AciveGroup("maiker1",true,outerr);ﻫserver.AciveGroup("maiker",false,outerr1);ﻫﻫ}

<4>、添加文本框、按钮等,并编写委托执行函数:

privatevoidDataChange(object[]obj,int[]itemsID)ﻫ{ﻫfor(intj=0;j

if(itemsID[j]==nt[0])ﻫthis.textBox1.Text=obj[j].ToString();

if(itemsID[j]==nt[1])ﻫthis.textBox4.Text=obj[j]。ToString();

}

}ﻫﻫ其中参数obj用于返回当前发生变化的变量的结果值,而itemsID返回当前发生变化的变量的ID号,其与添加变量时服务器返回的ID号对应。以上就是一个基本的测试函数,其相对同步编程来说,应该还简洁一些。ﻫ

3、同步编程与异步编程的使用场合ﻫﻫ一般来讲,同步编程需要使用定时器来循环检测变量,而异步编程则不需要,当服务器检测到数据发生变化时,可以直接调用传入的函数,从这方面来讲,使用异步编程更简洁一些,但同步编程使用外部的定时器掌握,编程则会更加灵敏,一般只监控变量时可以使用异步编程,而当需要写入数据时可以使用同步编程,但这也不是肯定的,我曾编写了一个标准监控程序,没有使用异步编程。ﻫﻫ4、关于开发监控界面的说明ﻫﻫ毫无疑问,我们应该开发一系列控件,用于简化界面的设计,否则工作量会特别大。设计一个标准模块,用于第一次运行监控软件时添加变量,并可以设定当前已经组态的界面中的各控件元素与之关联,这样在以后再运行该软件时,不需要再设定,就可以直接连接变量,并进行相应的变化.否则若在编程时编写代码进行关联,其工作量将会特别大。ﻫﻫ其实该类我早已经开发了,但始终没有时间写成文章,原来想开发一系列标准控件和标准模块,但由于换到上海工作,可能不会再有时间搞这方面的讨论了。ﻫﻫ作者:吴向阳

HYPERLINK”mailto:wuyang26@sohu.com”wuyang26@sohu。com如何开发OPCServer首先我们先来看一下什么是OPCOPC(OLEforProcessControl-—用于过程掌握的OLE)是基于Microsoft公司的DNA(DistributedInternetApplication)构架和COM(ComponentObjectModel)技术的一个工业标准接口,是依据易于扩展性而设计的.正在装载数据……再来了解一下OPC的用途OPC主要适用于过程掌握和制造自动化等应用领域。OPC是以OLE/COM机制作为应用程序的通讯标准。OLE/COM是一种客户/HYPERLINK"http://www.23/Server/Index.htm"服务器模式,具有语言无关性、代码重用性、易于集成性等优点。OPC规范了接口函数,不管现场设备以何种形式存在,客户都以统一的方式去访问,从而保证软件对客户的透明性,使得用户完全从低层的开发中脱离出来然后我们再来看看OPCServer的组成一个设备的OPCServer主要有两部组成,一是OPC标准接口的实现;二是与硬件设备的通信模块。实现OPC标准接口[图1]在这些接口中,IOPCServer是OPCServer的主接口,通过它实现OPCServer在操作系统中的安装和注册。此接口是必必要实现的,其全部方法也必须实现.其它的接口都是可选的我们就不做介绍了,下面主要来介绍如何实现IOPCServer接口。在IOPCServer接口中共有六个法:1、IOPCServer::AddGroupHRESULTAddGroup([in,string]LPCWSTRszName,[in]BOOLbActive,[in]DWORDdwRequestedUpdateRate,[in]OPCHANDLEhClientGroup,[unique,in]LONG*pTimeBias,[in]FLOAT*pPercentDeadband,[in]DWORDdwLCID,[out]OPCHANDLE*phServerGroup,[out]DWORD*pRevisedUpdateRate,[in]REFIIDriid,[out,iid_is(riid)]LPUNKNOWN*ppUnk);此方法是在OPCServer上建立一个组。下在我们来实现这个方法:…。….首先要对组名(szName)进行检查,看是否有效或是否已经有这个组.if(szName!=NULL){RequestedName=szName;if(RequestedName=="")RequestedName=pSvrObject-〉DefaultGroupName();}elseRequestedName=pSvrObject-〉DefaultGroupName();for(i=0;i<pSvrObject->NumbrGroups();i){pGroup=pSvrObject->GetGroup(i);if(RequestedName==pGroup—〉Name)return(OPC_E_DUPLICATENAME);}这需要在内存中维护OPCGroup(组)的列表(还要有OPC项的列表)。如果szName(组名)正确并且没有建立过该组,就开头依据传过来的参数进行组的建立,建立好后将该组加到自己的组列表中以备后用.最后将新建组的接口指针返回给客户端。2、IOPCServer::GetErrorStringHRESULTGetErrorString([in]HRESULTdwError,[in]LCIDdwLocale,[out,string]LPWSTR*ppString);为Server的错误代码返

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论