COM组件技术在现场总线控制系统组态软件中的应用
3.5 读适配器数据函数
除了向适配器发送数据,还可以从适配器上读取模块传上来的数据。读取数据的命令字是0xA5。实现该任务的函数是GetPV([in]BYTE bDesNode,[out]float value[8]),第一个参数是模块节点号,第二个参数是返回的测量值数组。
这里,COM是用ATL编写的本地服务器,COM对象的线程是套间线程。接口定义了6个函数,COM程序流程图如图2所示。
COM对象接口的函数声明以及适配器初始化的程序如下:
COM接口定义:
interface INCardWork :IDispatch
{
[id(1),helpstring("适配器初始化函数,返回值为是否成功")]
HRESULT NcardInit([in]BYTE
bSrcNode,[in]BYTE bIntrAdd,[in]BYTE bRate,[in]long bSegmantAdd,[out]BOOL *flag);
[id(2),helpstring("将客户端传送的数组赋值给Room[][]")]
HRESULT SendData[in]BYTE SendBuf[256]);
[id(3),helpstring("启动多线程")]javascript:window.open(this.src);" style="cursor:pointer;"/>
HRESULT SendFinish ([in]BOOL bFinish);
[id(4),helpstring("此函数返回值表示数据是否已向下位机发送完毕,同时可显示哪些模块未被配置,通常在此函数前先用FinishQuery([out]BOOL*bFinish)查询发送是否完毕")]
HRESULT ReceiveResult([out]BOOL *bSendFinish);
[id(5)],helpstring("此函数返回值表示数据是否已向下位机发送完毕,“真”表示发送完毕")]
HRESULT FinishQuery([out]BOOL *bFinish);
[id(6),helpstring("网络检查,用来在发送数据前检测是否有该节点存在")]
HRESULT NetCheck[in]BYTE sour,[in]BYTE des,[in]BYTE type,[out]BOOL *flag);
[id(7),helpstring("读取模块的测量值")]
HRESULT GetPV([iv]BYTE bDesNode,[out]float value[256]);
}
适配器初始化函数:
#include <conio.h>
#include "winioctl.h"
//包含其它头文件
……
STDMETHODIMP CNCardWork::NcardInit(BYTE bSrcNode,BYTE bIntrAdd,BYTE bRate,long bSegmentAdd,BOOL *flag)
{
NcardCtrl cardctrl; //NcardCtrl类的函数调用VxD函数
exbSrcNode=bSrcNode; //给上位机节点赋值
exbRate=bRate; //下位机与适配器的通信波特率
BOOL transfersign; //初始化是否成功标志
DWORD dwSegmentaddress=bSegmentAdd;//适配器段地址
HANDLE hDevice=NULL; //指向线性指针对句柄
LpBaseAddress=(PBYTE)cardctrl.MapLinearAddress(dwSegmentaddress,0x400,hDevice);
//调用VxD函数,获得指向ISA总线物理地址的线性地址指针
cardctrl,UnMapLinearAddress(lpBaseAddress,hDevice);
//关闭VxD
//调用适配器初始化函数
_outp(0x310,0x01); //打开邮箱锁
lpBaseAddress[0x3F0]=bSrcNodeNumber;//上位机节点号
lpBaseAddress[0x3F1]=bRate; //波特率
lpBaseAddress[0x3F8]=0xC6; //适配器初始化命令字
DrvDelay(20,false); //延时20ms
………… //初始化后其它操作
_outp(0x310,00); //关闭邮箱锁
return S_OK;
}
4 虚拟设备驱动程序
VxD是虚拟设备驱动程序(Virtual Device Driver)的缩写,中间的x表示某一设备。它能够无限制地访问所有硬件设备、自由地检测操作系统的数据结构(如描述符和页表)以及访问任何内存位置。
本文中,VxD将ISA总线对应的物理地址转换成段线性地址,供应用程序使用。VxD的开发工具是VtoolsD,转换时用的函数为MapPhysToLinear。以下是部分程序代码:
//定义结构体
typedef struct _MapDevRequest
{
PVOID mdr_PhysicalAddress;DWORD mdr_SizeInBytes;
PVOID mdr_LinearAddress;WORD mdr_Status;
}MAPDEVREQUEST,*PMAPDEVREQUEST;
#include<vtoolscp.h>
//包含其它头文件
…………
PARAMS pDIOCParams
{
PMAPDEVREQUEST pRea; //自己定义的结构体
switch(pDIOCParams->dioc_IOCtlCode)
{
case DIOC_OPEN:
case DIOC_CLOSEHANDLE:break;
case MDR_SERVICE_MAP:
pReq=*(PMAPDEVREQUEST*)pDIOCParams->dioc_InBuf;
pReq->mdr_LinearAddress=MapPhysToLinear
(pReq->mdr_PhysicalAddress,pReq->mdr_SizeInBytes,0);
if(pReq->mdr_LinearAddress==NULL)
pReq->mdr_Status=MDR_STATUS_ERROR;
else
pReq->mdr_Status=MDR_STATUS_SUCCESS;
break;
case MDR_SERVICE_UNMAP:break;
default:
return ERROR_INVALID_FUNCTION;
}
return DEVIOCTL_NOERROR;
}
在现场总线控制系统中使用COM组件技术,不仅可以使数据传输部分的功能独立于客户端程序,减小开发难度,而且使其可以被任何支持二进制代码的程序如Excel电子表格等直接调用。当系统中采用服务器和客户端方式时,代码更加易于维护。即使要升级服务器端程序,只要接口不变,其客户端程序也完全不需要修改,大量后续工作被减轻。象服务器端一样,客店端也只需关心服务器的接口,而不必考虑其如何实现数据交换。也就是说,COM服务器或客户机中的一端功能发生改变,只要其接口保持不变,另一端不需修改就可以工作。本文所介绍的技术已在胜利油田某注水站等实际工程项目中得到成功的应用。