一、引言现在有很多工业控制产品都支持OPCServer,如西门子SIMATICNET、WINCC、WINAC、Protool/pro,亚控公司组态王等,这些产品本身在一些需要实现很复杂的数据模型功能上还显得不足,由于支持了OPC,我们就可以在VB或C++上通过OPC获取数据进而实现较复杂的功能(如强大的数据库管理或数据分析)。本文讨论了如何在VB中开发一个动态连接库,以方便开发者实现对OPC服务器的数据采集,将精力更多的放在界面开发和数据处理上。二、功能设计类型设计为ActiveXDll,名称:OPC_Dll.dll,可以在VB工程[引用]中加载,加载后通过创建类BCA_OPC的实例来实现OPC数据通讯,BCA_OPC的调用功能如下:1、配置初始化:Dll_Initial(strConfigFileAsString)AsBoolean其中strConfigFile为连接OPC服务器对应的配置文件名称(*.ini),用户建立的配置文件应遵循一定的格式(在下面应用中说明),并且应放在系统目录下(如C:\WINNT下)。配置文件中包含了要连接的OPC服务器名称、log文件名称、变量组定义及对应组内的变量定义(本连接库最多支持1024个变量通讯,对变量组的数目没有限制)。配置成功返回TRUE。2、连接OPC服务器:ConnectServer(OptionalIPAddressAsString)AsBooleanIPAddress为可选的远程OPC服务器所属PC的IP地址,如“192.168.0.1”,如果不提供IPAddress参数,则默认为本机OPC服务器。连接成功返回TRUE。3、配置通讯变量(组态OPC客户机):SetConfiguration()AsBoolean根据提供的ini配置文件组态OPC客户机与服务器的变量通讯,组态成功返回TRUE。4、读变量数据:GetData(ItemNameAsString)ItemName为变量名称,必须与ini配置文件中的变量名称一致。本功能返回该变量的实际数据。5、写变量数据:WriteData(ItemNameAsString,ItemWriteDataAsVariant)ItemName为变量名称,ItemWriteData为变量数据。三、实现代码1、在VB6.0中新建ActiveXDll工程,如下图:2、在工程菜单中添加引用,如下图:如果系统中没有OPCAutomation,你需要安装注册OPC自动化。一般装了OPC支持的软件,系统都支持OPC自动化。3、在工程中添加模块,如下图:模块API_Function为软件所需的一些API函数。模块Global_constants为一些系统常量类模块BCA_OPC为实现主类类模块ItemInfo和ItemsInfo实现变量信息的封装4、以下为各模块的程序代码:API_Function:OptionExplicit'----------------------------------'获取一个与给定初始化文件指定域中的一个键相联系的整数值(1)PublicDeclareFunctionGetPrivateProfileIntLibkernel32Alias_GetPrivateProfileIntA(ByVallpApplicationNameAsString,ByVallpKeyNameAsString,_ByValnDefaultAsLong,ByVallpFileNameAsString)AsLong'从一个初始化文件中获取指定段的所有键和值(2)PublicDeclareFunctionGetPrivateProfileSectionLibkernel32Alias_GetPrivateProfileSectionA(ByVallpAppNameAsString,ByVallpReturnedStringAsString,_ByValnSizeAsLong,ByVallpFileNameAsString)AsLong'获取初始化文件中的制定断下的一个字符串(3)PublicDeclareFunctionGetPrivateProfileStringLibkernel32Alias_GetPrivateProfileStringA(ByVallpApplicationNameAsString,ByVallpKeyNameAsAny,_ByVallpDefaultAsString,ByVallpReturnedStringAsString,ByValnSizeAsLong,_ByVallpFileNameAsString)AsLongGlobal_constants:OptionExplicitOptionBase1'Globalconstrants'------------------------------GlobalConstEnglish=&H409GlobalConstOPC_DS_CACHE=1GlobalConstOPC_DS_DEVICE=2BCA_OPC:OptionExplicitOptionBase1'InterfaceObjects接口对象'----------------------------------------------------------------------------'必须使用WithEvents来申明对象OPCServer和OPCGroup,'WithEvents指定申明的对象用于处理对象的事件DimWithEventsServerObjAsOPCServer'定义OPCServerDimGroupObjAsOPCGroup'定义OPCGroupDimWithEventsGroupCollectionAsOPCGroups'定义OPCGroupsDimItemCollectionAsOPCItems'定义OPCItemsDimItemObjAsOPCItem'定义OPCItem'----------------------------------------------------------------------------'GlobalVariables全局变量'----------------------------------------------------------------------------DimServerNameAsString'OPC服务器名称DimServerConnectedAsBoolean'OPC服务器已连接标志'OPCServer和OPCGroup都有ServerHandle和ClientHandle参数;'ServerHandle用于OPC服务器定位;ClientHandle用于OPC客户端定位;DimServerGroupHandle()AsLong'服务器-组句柄(索引)DimServerItemHandle()AsLong'服务器-条目句柄DimClientGroupHandle()AsLong'客户机-组句柄DimClientItemHandle()AsLong'客户机-条目句柄DimDll_is_InitialAsBoolean'DLL初始化DimConfiguration_is_SetAsBoolean'是否已组态DimTraceOnAsBoolean'跟踪开关DimTraceFileAsString'跟踪文件DimConfigFileAsString'组态文件DimItemData(1024)AsVariant'读取变量数据的储存地址DimAllItemsInfoAsNewItemsInfo'log文件记录操作PrivateFunctionTrace(TraceMsgAsString)IfTraceOn=TrueThenDimfsAsObject,fAsObjectDimmHour,mMinute,mSecond,mMSecondAsStringSetfs=CreateObject(Scripting.FileSystemObject)Setf=fs.OpenTextFile(TraceFile,8,-2)mHour=Format(Fix(Timer/3600),00)mMinute=Format(Fix((Timer-mHour*3600)/60),00)mSecond=Format(Fix((Timer-mHour*3600-mMinute*60)),00)mMSecond=Format(Fix((Timer-Fix(Timer))*1000),000)f.Writeline[&mHour&:&mMinute&:&mSecond&.&mMSecond&]&TraceMsgf.CloseSetfs=NothingSetf=NothingEndIfEndFunction'(1).DLL初始化PublicFunctionDll_Initial(strConfigFileAsString)AsBooleanDimResultAsString*255,fsAsObject,fAsObjectConfigFile=strConfigFileGetPrivateProfileStringTRACE,TraceOn,_ERROR,Result,255,ConfigFileIfResultERRORThenIfResult=1ThenGetPrivateProfileStringTRACE,TraceFile,_ERROR,Result,255,ConfigFileIfResultERRORThenTraceFile=ResultElseTraceFile=App.Path&\Trace.logEndIfSetfs=CreateObject(Scripting.FileSystemObject)Setf=fs.CreateTextFile(TraceFile,True)f.Writeline(***BCA_OPCTraceStarted,BeiChenAutomation2003/ZhangPeng***)f.CloseTraceOn=TrueElseTraceOn=FalseEndIfDll_is_Initial=TrueDll_Initial=TrueTraceDll_InitialTraceDll_InitialOKElseMsgBox无法找到配置文件:&strConfigFile,vbOKOnly,错误Dll_is_Initial=FalseDll_Initial=FalseEndIfEndFunction'(2).连接OPC服务器PublicFunctionConnectServer(OptionalIPAddressAsString)AsBooleanTraceConnectServerIfDll_is_Initial=FalseThenTraceConnectServerCancelled,BecauseDll_InitialhasnotbeencalledExitFunctionEndIfIfNotServerConnectedThenServerName=GetServerNameOnErrorGoToErrorHandlerSetServerObj=NewOPCServerServerObj.ConnectServerName,IPAddressServerConnected=TrueTraceConnectServerOKElseTraceServerhasbeenconnected,PleasedonotconnectitagainEndIfConnectServer=ServerConnectedExitFunctionErrorHandler:TraceConnectServerError,PleasebesurethatServerisrunningConnectServer