版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
并行接口程序设计本章介绍在Windows2000/XP下的并行接口的程序设计方法,分析一下目前进行并行接口编程的方法,可以归纳为几种:DLL直接I/O方式:应用程序通过一个可以进行端口I/O访问的DLL接口软件实现对并行接口的访问,即通过调用第三方DLL接口软件中的I/O端口读写函数实现对并行口的寄存器的读写。这样的软件很多,像Winlo、Inpout32、TVicPort等;ActiveX控件直接I/O方式:通过一个提供ActiveX控件实现对端口的直接I/O访问,一般控件的方式采用VB编程比较简单。这样的软件包括Inpout32、TVicPort等;•并行接口专用接口软件:使用这一类软件对并行接口编程要比上2种方法简单,有些软件支持中断。这样的软件如TVicLPTo自己编写驱动程序:直接在VC++环境下通过Windows2000DDK或WindowsXPDDK编写驱动程序,这是一种最灵活的方法,但编程的难度比较大。5.1实现直接I/O方式的软件并行接口的编程在不同的操作系统下采取不同的方法,在DOS和Windows95之前的操作系统下,可以直接对端口进行读写,根据并行接口的不同模式的寄存器进行读写操作就可以完成各种模式的接口编程。在目前的Windows2000/XP操作系统下,不能直接对端口寄存器进行访问,这是由于Windows2000/XP对系统底层操作采取了屏蔽的策略,对用户而言,系统变得更为安全,但这却给接口和接口软件开发人员带来了不小的困难,因为只要应用程序中涉及到底层的操作,开发人员就不得不深入到Windows的内核去编写属于系统级的设备驱动程序。对并行口的读写操作就是如此,由于Windows对系统的保护,应用程序不允许直接I/O操作。在Windows2000/XP操作系统下,正规的接口程序的编程方法是采取驱动程序的开发方法。由于驱动程序需要与操作系统最底层进行交互,因此不同的操作系统的底层结构对应不同的设备驱动程序模型。Windows2000/XP与Windows9x的内部结构不同,这两类操作系统的设备驱动程序是不兼容的,为了解决不同的操作系统的结构的差异带来的设备驱动程序的不兼容的问题,微软公司在1997年提出了Windows操作系统的驱动程序模型,即WDM(WindowsDriverModel)oWDM设备驱动程序的开发是在VC++下通过DDK(DeviceDevelopmentKit:设备驱动程序开发包)才能完成的,这种方法的编程是比较复杂的,需要了解操作系统的内部结构,并需要熟练的VC++开发经验。如果不采用WDM的方法,一个简单实用的方法是使用间接的I/O方式,就是在应用程序调用一个第三方提供的直接I/O接口程序,由这个间接的I/O程序模块实现对端口的读写。下面介绍几种这样的软件产品。Inpout32Inpout32:由LOGIX4U提供的免费软件,可以在/网站下载。Inpout32提供了以DLL文件和AxtiveX的OCX文件两形式提供了直接访问I/O端口的函数,在文件中只封装了2个函数,Inp32()和Out32()。支持从Windows95/98/Me到WindowsNT/2000/XP的多种操作系统。Inpout32只提供对I/O端口的访问,不针对具体的接口类型,原则上可以完成所有面向寄存器访问编程的应用程序。但Inpout32没有提供中断的支持,所以只能完成以查询控制方式的程序,不能实现中断控制方式的程序设计。这可能会影响接口的传输速度,同时也使得软件的CPU占用率很高。很可贵的是,在下载的软件包中提供了DLL和OCX文件的VC++源程序代码,这对于开发接口相关的DLL程序和OCX控件程序很有参考价值。TVicPortEnTech提供了用于接口编程的多个软件产品,包括TVicTW32、TVicLPT和TVicPort等,这些软件可以在EnTech的网站/dev/index.shtm上获得,其中TVicPort是一个免费的软件,是TVicHW32的简化版。TVicPort是需要安装的,默认的目录是C:\TVicPortPersonal,在该目录下有Docs和Samples两个目录,分别是说明文件和程序例子源文件。核心模块被安装到了系统目录。TVicPort功能说明TVicPort的功能包括:・直接I/O访问;-通过一个指针将物理存储器影射用户程序的存储空间;-增强对并行接口的支持,可以直接控制和检测并行端口的信号线;-提供获得IDE硬盘的制造商信息的函数,如硬盘序列号,可以实现软件的硬盘邦定;・支持WindowsXP64bit。TVicPort提供的核心模块文件包括TVicPort.sys、TVicPort.vxd、TVicPort.dll和TVicPort.ocx四个。其中TVicPort.vxd是用于Windows9x/ME的虚拟设备驱动程序,TVicPort.sys是用于Windows2000/XP的内核模式驱动程序,DLL和OCX是应用程序接口模块,实现应用程序与设备驱动程序的连接。虽然TVicPort支持多种语言平台,但DLL函数更适合用于VC++编程,而OCX文件适合用于VB编程。TVicPort提供两种对于端口的访问方式,即“Hard”和“Soft”方式,其中“Soft”方式的读写速度比较快,但当被读写的端口地址被另一个内核模式驱动程序占用时会访问失效。而“Hard”方式可以避免这种情况,即使端口被另一个内核模式驱动程序占用也能完成可靠的读写,但其访问速度比“Soft”方式慢。函数默认的访问方式是“Hard”方式,可以使用SetHardAccess()函数更改访问方式。也可以通过函数TestHardAccess(涵数返回当前的访问方式。TVicPort的DLL函数下面介绍TVicPort的DLL文件提供的VC++格式接口函数。这些函数的原形说明在TVicPort.h中,在VC++中加入TVicPort.h后可以直接按照下面介绍的格式实现调用。如果在VB中调用这些函数,可以在VB工程中加入\Samples\VB\PortLib.bas模块,在模块中对全部函数作了声明,可以参照模块中的声明细节实现在VB中的调用。TVicPort.dll提供的公共函数BOOLOpenTVicPort():打开(加载)TVicPort.vxd或TVicPort.sys设备驱动。参数:无。返回:打开成功返回TRUE,失败返回FALSE。BOOLIsDriverOpened():测试驱动程序是否打开。参数:无。返回:驱动程序已打开返回TRUE,未打开返回FALSEovoidCloseTVicPort():关闭(卸载)设备驱动程序。voidSetHardAccess(BOOLHardAccess):设置当前的访问方式为“Hard”或“Soft”参数:TRUE表示设置为“Hard”方式,FALSE表示设置为“Soft”方式。返回:无。BOOLTestHardAccess():测试当前的访问方式。参数:无。返回:TRUE表示“Hard”方式,FALSE表示“Soft”方式。TVicPort.dll提供的端口访问函数UCHARReadPort(USHORTPortAddr)读端口1个字节。USHORTReadPortW(USHORTPortAddr)读端口2个字节(字)。ULONGReadPortL(USHORTPortAddr):读端口4个字节(双字)。参数:端口地址。返回:读得的端口数据。voidWritePort(USHORTPortAddr,UCHARbData:写1个字节到端口。voidWritePortW(USHORTPortAddr,USHORTwData)写2个字(字)节到端口。voidWritePortL(USHORTPortAddr,ULONGlData:写4个字节(双字)到端口。参数:PortAddr为端口地址,bData/wData/lData为要写的数据。返回:无。voidReadPortFIFO(USHORTPortAddr,USHORTNumPorts,UCHAR*Buffer)voidReadPortWFIFO(USHORTPortAddr,USHORTNumPorts,USHORT*Buffer)voidReadPortLFIFO(USHORTPortAddr,USHORTNumPorts,ULONG*Buffer)功能:读取多个单元(字节/字/双字)到一个输入缓冲区。参数:PortAddr为端口地址,NumPorts为单元数,Buffer为输入缓冲区指针。voidWritePortFIFO(USHORTPortAddr,USHORTNumPorts,UCHAR*Buffer)voidWritePortWFIFO(USHORTPortAddr,USHORTNumPorts,USHORT*Buffer)voidWritePortLFIFO(USHORTPortAddr,USHORTNumPorts,ULONG*Buffer)功能:写多个单元(字节/字/双字)到端口。参数:PortAddr为端口地址,NumPorts为单元数,Buffer为输出缓冲区指针。TVicPort.dll提供的存储器访问函数ULONGMapPhysToLinear(ULONGPhysAddr,ULONGMappedSize)功能:映射系统的物理存储器空间到应用程序的线性存储空间。参数:PhysAddr为32位物理存储器起始地址,MappedSize为映射的字节数。返回:物理存储器空间的首字节映射到线性存储空间的地址。voidUnmapMemory(ULONGPhysAddr,ULONGMappedSize)功能:关闭由MapPhysToLinear(涵数建立的映射。参数:PhysAddr为32位物理存储器起始地址,MappedSize为映射的字节数。返回:无。UCHARGetMem(ULONGMappedAddress,ULONGMemOffset)USHORTGetMemW(ULONGMappedAddress,ULONGMemOffset)ULONGGetMemL(ULONGMappedAddress,ULONGMemOffset)功能:读取线性存储空间的字节/字/双字数据,以上3个函数可以用于VB,因为在VC++中可以直接通过指针实现线性地址空间的数据读取,而VB缺乏指针的操作手段。参数:MappedAddress为由MapPhysToLinear(涵数返回的线性存储空间的首地址,MemOffset为线性存储空间的偏移位置。返回:读取的数据。voidSetMem(ULONGMappedAddress,ULONGMemOffset,UCHARbValue)voidSetMemW(ULONGMappedAddress,ULONGMemOffset,USHORTwValue)voidSetMemL(ULONGMappedAddress,ULONGMemOffset,ULONGdwValue)功能:向线性存储空间写入一个字节/字/双字数据,以上3个函数可以用于VB,因为在VC++中可以直接通过指针实现线性地址空间的数据读取,而VB缺乏指针的操作手段。参数:MappedAddress为由MapPhysToLinear(涵数返回的线性存储空间的首地址,MemOffset为线性存储空间的偏移位置,bValue/wValue/dwValue为要写入的数据。返回:无。(4) TVicPort.dll提供的并行接口访问函数UCHARGetLPTNumber():获得当前的并行接口号。参数:无返回:1为LPT1,2为LPT2...。voidSetLPTNumber(UCHARLptNumber):设置一个并行口为当前并行口。参数:lptNumber为1表示LPT1,2表示LPT2...。返回:无。UCHARGetLPTNumPorts():检测系统中的LPT数目。参数:无。返回:系统中的LPT数目。ULONGGetLPTBasePort():获得当前LPT的基地址。参数:无。返回:当前LPT基地址。UCHARAddNewLPT(USHORTPortBaseAddress:添加一个LPT。参数:PortBaseAddress为添加的LPT的基地址。返回:添加的LPT的号码,同时设置添加的LPT为当前LPT。BOOLGetPin(UCHARPinNumber):读取当前LPT连接器的可读取线状态。参数:PinNumber为DB25连接器的线编号,1〜25。返回:TRUE表示高电平,FALSE表示低电平。voidSetPin(UCHARPinNumber,BOOLPinLevel)设置当前LPT的可写线状态。参数:PinNumber为DB25连接器的线编号,PinLevel为TRUE表示高电平,FALSE表示低电平。返回:无。BOOLGetLPTAckwl()获得当前LPT的Acknowledge线状态。参数:无。返回:TRUE表示有效,FALSE为无效状态。BOOLGetLPTBusy():获得当前LPT的Busy线状态。参数:无。返回:TRUE表示有效,FALSE为无效状态。BOOLGetLPTPaperEnd():获得当前LPT的PaperEnd线状态。参数:无。返回:TRUE表示有效,FALSE为无效状态。BOOLGetLPTSlct():获得当前LPT的Slct线状态。参数:无。返回:TRUE表示有效,FALSE为无效状态。BOOLGetLPTError():获得当前LPT的Error线状态。参数:无。返回:TRUE表示有效,FALSE为无效状态。voidLPTInit():在当前LPT的Init线(DB25的16号引脚)输出一个短暂的脉冲。参数:无。返回:无。voidLPTSlctIn():设置当前LPT的SelectIn线为有效。参数:无。返回:无。voidLPTStrobe():在当前LPT的Strobe线(DB25的1号引脚)输出一个短暂的脉冲。参数:无。返回:无。voidLPTAutofd(BOOLFlag):设置当前LPT的AutoLF线(DB25的14号引脚)状态。参数:Flag为TRUE表示有效,FLASE表示无效。返回:无。(5)TVicPort.dll提供的IDE硬盘访问函数voidGetHDDInfo(UCHARIdeNumber,UCHARMaster,HDDInfo*Info)功能:返回IDE硬盘的制造商参数。参数:IdeNumber为IDE通道号,Masker为1表示Masker设备,0表示Slave设备。*Info为指向一个HDDInfo结构的指针,该函数填写HDDInfo。返回:无。HDDInfo结构如下:
typedefstruct_HDDInfo{ULONGBufferSize;〃缓冲存储器容量ULONGDoubleTransfer;〃双字节数据传输支持ULONGControllerType;〃控制器类型ULONGECCMode;//ECC校验模式ULONGSectorsPerInterrupt;〃每中断的扇区数ULONGCylinders;〃柱面数ULONGHeads;〃磁头数ULONGSectorsPerTrack;〃每磁道扇区数charModel[41];〃型号charSerialNumber[21];〃序列号charRevision[9];}HDDInfo,*pHDDInfo;〃控制器版本号TVicPort的ActiveX控件TVicPort的ActiveX控件属性和DLL函数接口基本功能是类似的,个别DLL函数在ActiveX控件没有。ActiveX控件的接口方式更适合在VB中使用。当然并不是在VB中必须使用TVicPort的ActiveX控件方式,也可以采用DLL方式调用TVicPort.dll中的函数。首先在VB中创建一个StandardEXE类型的工程,选择Project菜单中的Components菜单项,打开Components窗口,在Controls选项卡中找到TVicPortActiveXControlModele,选中后按确定按钮将TVicPort控件插入到Toolbox中,在将其拖到应用程序的窗体中,在窗体呈现一个TVP标记,然后就可以编写代码了。TVicPort的ActiveX属性成员名称和功能与DLL函数的有差别,全部的ActiveX属性成员以及和DLL函数的对应关系见下表。表5-1PVicPort的ActiveX属性成员以及和DLL函数的对应关系ActiveX属性成员对应功能的DLL函数OpenDriverOpenTVicPortActiveHWIsDriverOpenedCloseDriverCloseTVicPortHardAccessSetHardAccess、TestHardAccessPortReadPort、WritePortPortWReadPortW、WritePortWPortLReadPortL、WritePortLMapPhysToLinearMapPhysToLinearUnmapMemoryUnmapMemoryMemGetMem、SetMemMemWGetMemW、SetMemWMemLGetMemL、SetMemLLPTNumberGetLPTNumber、SetLPTNumberLPTNumPortsGetLPTNumPortsLPTBasePortGetLPTBasePortPinGetPin、SetPinLPTAckwlGetLPTAckwlLPTBusyGetLPTBusyLPTPaperEndGetLPTPaperEndLPTSlctGetLPTSlctLPTErrorGetLPTErrorLPTInitLPTInitLPTSlctInLPTSlctInLPTStrobeLPTStrobeLPTAutofdLPTAutofdTVicLPTTVicLPT是EnTech提供的并行接口的专用接口软件,该软件包本身不是免费的,但公司网站上还提供了一个免费TVicLPT全功能评估版本。可以在EnTech的网站/dev/index.shtm上下载。TVicLPT是需要安装的,TVicLPT1.3版默认的安装目录是C:\TVicLPT13,在该目录下有Help目录和各种语言的测试程序源代码目录。核心模块TVicLPT.ocx和TVicLPT.sys被安装到了系统目录。TVicLPT功能说明TVicLPT1.3版只提供ActiveX控件文件,没有提供DLL方式的函数调用接口。该控件支持多种语言调用,在安装的目录下可以找到VB、MSVC、BorlandC++Builder和BorlandDelphi的测试程序代码。TVicLPT的功能包括:・检测标准的地址上的并行端口;-具备添加非标准的并行口的能力;・检测并行口支持的模式,包括SPP、PS/2、EPP和ECP等;-可以在不进行位操作的情况下实现并行口模式的转换;・通过“名字”实现对并行口的直接访问;-直接访问和操作LPT的连接器上的信号;・实现硬件中断的挂接。TVicLPT的ActiveX控件属性成员下面以VB语法格式说明TVicLPT的ActiveX控件的属性成员。(1) 公共的属性和方法object.Active[=value]功能:打开/关闭设备驱动程序,或检测设备驱动程序打开状态。参数:Value为设置参数,1表示打开第一个驱动程序实例,2表示打开第二个驱动程序实例,0表示关闭驱动程序。返回:1表示成功打开驱动程序,0表示为打开或打开失败。object.NumLPTs功能:检测系统安装的标准的LPT数目。参数:无。返回:LPT数目。object.AddCustomPort(CustomBaseAddressAsInteger)功能:添加非标准的(无法通过NumLPTs检测到的)LPT到系统。参数:CustomBaseAddress为添加的LPT的基地址。返回:无。object.Acquired[=value]功能:锁定当前的LPT以防止被其他应用程序访问,或检测锁定状态。该属性成员只用于Windows9x/ME。参数:value为设定值,1表示锁定,0表示为锁定或解除锁定。返回:可以是以下常数(在lptCVT.bas中定义)LPT_NOT_ACQUIRED:未锁定;LPT_ACQUIRE_SUCCESS:锁定成功;LPT_ACQUIRE_REFUSED:已经被另一个应用程序锁定;LPT_ACQUIRE_BAD_PORT:LPT号错误或操作系统为Windows2000/XP;LPT_ACQUIRE_NOT_OPENED:设备驱动程序未打开。(2) 当前LPT和模式的属性和方法object.CurrentLPT[=value]功能:设置或获得当前LPT号。参数:value为设定值,表示LPT号。返回:当前LPT号。object.CurrentLptMode[=value]功能:设置或获得当前LPT的当前工作模式。参数:value为设定值,表示模式,可以是以下常数(在lptCVT.bas中定义)LPT_SPP_MODE:SPP模式;LPT_PS2_MODE:PS/2模式;LPT_EPP_MODE:EPP模式;LPT_FAST_CENTRONIX:Centronix模式;LPT_ECP_MODE:ECP模式。返回:获得的当前LPT的工作模式,值的定义同上。object.MaxLptMode功能:获得当前LPT支持的“最大”工作模式。参数:无。返回:“最大”工作模式值。可以是以下常数(在lptCVT.bas中定义)LPT_NOT_PRESENT=0LPT_SPP_MODE=1LPT_PS2_MODE=2LPT_EPP_MODE=3LPT_FAST_CENTRONIX=4LPT_ECP_MODE=5object.EPPEnabled功能:检测当前的LPT是否支持EPP模式。参数:无。返回:TRUE表示支持EPP,FALSE表示不支持EPP模式。LPT寄存器相关的属性和方法object.BasePortAddress功能:返回当前LPT的基地址。参数:无。返回:当前LPT的基地址值。object.ReadMode[=value]功能:设置或返回当前LPT的数据寄存器的读写状态。参数:value为设定值,0表示“只写”,1表示“只读”。SPP不支持“只读”。返回:TRUE表示“只读”模式,FALSE表示“只写”模式。object.DataPort[=value]object.StatusPort[=value]object.ControlPort[=value]object.EcrPort[=value]object.CfgaPort[=value]object.CfgbPort[=value]object.FifoPort[=value]object.EPPAddressPort[=value]object.EPPDataPort[=value]功能:以上9个属性成员用于从当前LPT不同的寄存器读或向当前LPT不同的寄存器写数据。它们针对的寄存器分别为数据寄存器、状态寄存器、控制寄存器、ECR寄存器、CFGA寄存器、CFGB寄存器、FIFO寄存器、EPP地址寄存器和EPP数据寄存器。参数:value为设定值,为写到当前LPT的相应寄存器的数据。返回:从当前LPT的相应寄存器读出的数据。LPT寄存器位相关的属性和方法object.DataPortBit(BitNumberAsInteger)[=value]object.StatusPortBit(BitNumberAsInteger)[=value]object.ControlPortBit(BitNumberAsInteger)[=value]object.EcrPortBit(BitNumberAsInteger)[=value]object.CfgaPortBit(BitNumberAsInteger)[=value]object.CfgbPortBit(BitNumberAsInteger)[=value]功能:以上6个属性用于设置或返回当前LPT的不同寄存器的指定位。6个不同属性分别对应数据寄存器、状态寄存器、控制寄存器、ECR寄存器、CFGA和CFGB寄存器。参数:BitNumber参数为位序号,0~7。value为设定值,0或1。返回:获得的不同的寄存器的指定位的值,0或1。(5) LPT连接器位相关的属性和方法object.Pin(PinNumberAsInteger][=value]功能:用于设置或返回当前LPT的DB25连接器上的指定线的信号状态。当前LPT的读写状态(由ReadMode属性设定)将影响该属性成员的执行。参数:PinNumber参数为连接器线序号,1~25。value为设定值,0或1。返回:获得的线状态,TRUE为高电平,FALSE为低电平。object.PulseStrobe(By^alDelayCyclesAsLong)功能:在当前LPT的Strobe线(DB25的1号引脚)输出一个短暂的正脉冲。参数:DelayCycles参数为一个和输出脉冲宽度相关的相对时间间隔,如为0表示尽可能的短。返回:无。object.PulseStrobeAndWaitBus(TimeOutAsInteger)功能:在当前LPT的Strobe线(DB25的1号引脚)输出一个短暂的正脉冲,但只有当外设送到接口的BUSY线信号变为有效状态才结束Strobe线的脉冲。参数:TimeOut参数为一个相对的时间间隔表示等待BUSY信号的超时时间。返回:TRUE表示成功,未超时;FALSE表示超时。(6) 中断相关的属性和方法object.IrqNumber[=value]功能:设置和获得当前LPT的中断号。参数:value是一个设定值,指定中断号,取值范围为1〜15。通常LPT1使用中断7,LPT2使用中断5。返回:当前使用的中断号。object.UnmaskIRQ功能:解除当前LPT中断屏蔽,当硬件产生,将引发一个LptInterrupt事件。参数:无。返回:无。object.MaskIRQ功能:屏蔽当前LPT中断。参数:无。返回:无。object.IrqCounter功能:获得当前LPT发生的中断数量。参数:无。返回:中断数。object_LptInterruptBjV^ZDataPortAsInteger,ByValStatusPortAsInteger,_ByValTimeStampLoAsLong,ByValTimeStampHiAsLong)功能:当LPT的硬件产生中断时调用的函数。参数:DataPort和StatusPort产生中断时的数据寄存器和状态寄存器,TimeStampLo和TimeStampHi分别为时间邮票的低半部分和高半部分,参见API函数QueryPerformanceCounter()。批量读写相关的方法object.ReadEppByteArrayfByValNumOfBytesAsLong,ByRefByteBufferAsAny)object.ReadEppWordArray(ByValNumOfWordsAsLong,ByRefWordBufferAsAny)object.ReadEppLongArray(ByValNumOfDWordsAsLong,ByRefLongBufferAsAny)功能:这三个函数使用在EPP模式,分别用于读取字节、字和双字型数组。参数:NumOfBytes、NumOfWords和NumOfDWords分别为三个函数读取的字节、字和双字数,ByteBuffer、WordBuffer和LongBuffer分别为三个函数的输入数据缓冲区。object.WriteEppByteArray(ByValNumOfBytesAsLong,ByRefByteBufferAsAny)object.WriteEppWordArray(ByValNumOfWordsAsLong,ByRefWordBufferAsAny)object.WriteEppLongArray(ByValNumOfDWordsAsLong,ByRefLongBufferAsAny)功能:这三个函数使用在EPP模式,分别用于向LPT写字节、字和双字型数组。参数:NumOfBytes、NumOfWords和NumOfDWords分别为三个函数要写入的字节、字和双字数,ByteBuffer、WordBuffer和LongBuffer分别为三个函数的输出数据缓冲区。5.2一个PC对等连接的并行接口测试实验进行并行接口实验的简单方法是将两台pc通过一条并行接口电缆连接起来,可以通过软件测试并行接口的一些特性。本节介绍一个这样的并行接口实验。5.2.1对等连接工作模式在对等连接中,并行接口必须工作在可以双向传输的模式,在现有的IEEE-1284标准中,PS/2、EPP和ECP支持字节双向传输。在这三种模式中,PS/2和ECP模式比较适合对等连接。在PS/2模式中,握手信号可以自由的收程序的控制,本实验选择PS/2模式。连接电缆由于并行接口最初的设计是针对打印机的,尽管在后续的升级中增加了多种模式,但有一点是没有改变的,就是并行接口的设计是用于连接主机与外设的,如果使用并行接口连接两台主机,实现对等连接,可能要对接口信号线的功能作一些调整,设计一个合理的连接方案是遇到的第一个问题。在并行接口的信号线中,有8条双向数据线D0〜D7,8条地线,4条控制输出线和5条状态输入线。通过连接电缆将两端PC并行口的数据线和地线对应引脚连接,再将一端的4条控制输出线与另一端的5条状态输入线中的4条连接。下面的连接中可考虑到了ECP
模式的信号连接关系。表5-2并行接口的ECP模式PC-PC连接电缆A端计卜算机接口线中间连接B端计算机接口线信号名寄存器位线号线号寄存器位信号名nStrobeC01>>10S6nAck数据线D02[1k]2D0数据线D13[1k]3D1D24[1k]4D2D35[1k]5D3D46[1k]6D4D57[1k]7D5D68[1k]8D6D79[1k]9D7nAckS610<<1C0nStrobeBusyS711<<14C1nAutoFdPErrorS512<<16C2nInitnAutoFdC114>>11S7BusySelectS413<<17C3nSelectInnInitC216>>12S5PErrornSelectInC317>>13S4SelectGround18..2518..25Ground电缆的连接关系如下图。
图5-1ECP的PC-PC连接器关系5.2.2软件设计测试程序在VB下设计,并行接口的操作通过TVicLPT控件实现。1.测试程序的功能测试程序是为了测试并行接口在PS/2模式的功能,主要实现以下功能:・可以完成对控制寄存器的位操所,通过对控制寄存器的位操作实现对接口信号线的状态控制;・可以实时检测信号线的状态,这是通过读状态寄存器实现的。需要在定时器的控制下读取状态寄存器;-可以实现对数据寄存器的读写;・可以检测中断的产生;・可以实现字符传输。2.程序定时的实现虽然在程序中使用了Timer控件,但是不能使用该控件完成超时控制,Timer控件定时器完成超时控制会出现以下问题:-VB中的Timer控件产生的时间间隔的精度很低,它的硬件时钟的更新频率为每秒约18次,不能完成高精度的定时要求;在程序上,如果采用查询控制方式,接收程序代码部分实际上是在状态查询定时器的事件触发下执行的,这样在接收数据的过程中就无法使用状态查询定时器完成计时。本程序中使用一个系统定时器,通过API函数获得定时器的当前值,相关的API函数为QueryPerformanceCounter和QueryPerformanceFrequency,分别用于获得系统定时器的计数值和技术频率。需要在VB程序中对这两个API函数声明,用以下代码声明。DeclareFunctionQueryPerformanceCounterLib"Kernel32”(XAsCurrency)AsBooleanDeclareFunctionQueryPerformanceFrequencyLib"Kernel32”(XAsCurrency)AsBoolean在读数据、写数据和等待一个状态时都可以在开始时刻调用QueryPerformanceCounter函数获得开始的时刻,在操作过程中再调用该函数获得当前的时间,用以下公式计算时间:(当前时刻一开始时刻)『定时器频率在程序中可以使用以下语句获得系统定时器频率SysCountFrequency:Result=QueryPerformanceFrequency(SysCountFrequency)在需要记忆时间的位置插入以下语句可以获得当时的系统定时器常数SysCount:Result=QueryPerformanceCounter(SysCount)程序使用的控件说明程序使用VB实现。首先建立一个StandardEXE工程,将TVicLPTActiveXControlModule加入到VB的Form中,默认名称是TVicLPTl。程序中添加的全部控件见下表。表5-3并行接口对等连接测试程序使用的控件控件名称控件类型功能说明TVicLPTlTVicLPT访问接口的控件frmModeFrame包含optPS2Mode和optECPMode的容器optPS2ModeOptionButton选择PS/2模式optECPModeOptionButton选择ECP模式frmlnterruptFrame包含中断和传送的控件容器chkInterruptCheckBox控制中断使能lblAckIntLabel中断计时器,计数由nAck产生的中断txtDataTrsTextBox传送的数据字节值,发送后程序控制加1txtDataRcvTextBox接收到的数据字节值cmdTransCommandButton数据字节发送按钮chkReadyCheckBox用于设定接收就绪状态cmdReadDataCommandButton读取数据寄存器
cmdWriteDataCommandButton写数据寄存器txtDataTextBox数据寄存器的读写数据lblDataLabel数据寄存器的读写数据的十六进制和二进制cmdRegisterCommandButton读取控制寄存器和状态寄存器按钮chkAutoRegisterCheckBox自动读取控制寄存器和状态寄存器使能cmdControl()CommandButton阵列,用于改变状态寄存器的位lblStatus()Label阵列,用于显示状态寄存器的位Timer1Timer自动读取控制和状态寄存器的定时器程序界面程序设计界面如下。图5-2并行接口对等连接测试程序界面程序运行后,如果并行接口支持PS/2模式,LPTMode容器中的PS/2选中。右下方的6个按钮对应控制寄存器的C0〜C5位,可以通过按钮分别控制对应位的值,C0〜C4分别对应接口的1(nStrobe)、14(nAutoFd)、16(nInit)和17(nSelectIn)引脚,C4为IRQEnable,中断使能控制,C5位是方向控制位。状态寄存器的S2〜S7位有定义,S2(IRQ)为中断状态位,S3〜S7为接口引脚15(nFault)、13(Select)、12(PError)、10(nAck)和11(Busy)的状态。当AutoRegisiter选中,状态位显示的更新通过定时器自动完成,否则需要通过Regisiter按钮手动更新显示。ReadData和WriteData按钮分别用于读、写数据寄存器。下方显示数据寄存器的数值。TransData容器用于控制中断和数据传输,发送方按TransData按钮可以发送数据到对方,接收方需要选中ReadyReceive,使得接收PC机处于接收就绪状态。在数据传送过程中,发送方没发送一个字节,发送数据字节值自动加1。接收方可以观察中断计数值InterruptCount确认中断的产生,以及接收数据值确认传输的正确性。程序代码全程变量DimSRAsByte,CRAsByte,ECRAsByteDimResultAsBooleanDimSysCountFrequencyAsCurrency,SysCount1AsCurrency,SysCount2AsCurrency选择定时器控制自动更新寄存器,打开、关闭定时器PrivateSubchkAutoregister_Click()IfchkAutoRegister.Value=0ThenTimer1.Enabled=FalseElseTimer1.Enabled=TrueEndIfEndSub选择打开、关闭中断PrivateSubchkInterrupt_Click()IfchkInterrupt.Value=0ThenTVicLPT1.MaskIrqElseTVicLPT1.UnmaskIrqEndIfEndSub设定、取消接收就绪PrivateSubchkReady_Click()IfchkReady.Value=1ThenTVicLPT1.ControlPortBit(0)=0TVicLPT1.ControlPortBit(1)=1TVicLPT1.ControlPortBit(5)=1chkInterrupt.Value=1TVicLPT1.UnmaskIrqTimer1.Enabled=FalsechkAutoRegister.Value=0ElsechkInterrupt.Value=0TVicLPTl.MaskIrqTimerl.Enabled=TruechkAutoRegister.Value=1EndIfEndSub读取控制和状态寄存器内容PrivateSubcmdregister_Click()Timer1_TimerEndSub传输字节到对方计算机PrivateSubcmdTrans_Click()IfTVicLPT1.StatusPortBit(7)=0ThenExitSubTVicLPT1.ControlPortBit(5)=0TVicLPT1.DataPort=Val(txtDataTrs.Text)TVicLPT1.ControlPortBit(0)=1TVicLPT1.ControlPortBit(0)=0IfWaitStatus(100,7,1)ThenTVicLPT1.ControlPortBit(1)=0IfWaitStatus(100,7,0)ThentxtDataTrs.Text=IIf(Val(txtDataTrs.Text)=255,"0”,Str(Val(txtDataTrs.Text)+1))EndIfTVicLPT1.ControlPortBit(1)=1EndIfTVicLPT1.ControlPortBit(5)=1EndSub中断处理,读取数据并完成握手PrivateSubTVicLPT1_LptInterrupt(ByValDataValueAsInteger,ByValStatusValueAsInteger,_ByValLoTimeStampAsLong,ByValHiTimeStampAsLong)IfTVicLPT1.StatusPortBit(6)=1ThentxtDataRcv.Text=TVicLPT1.DataPortTVicLPT1.ControlPortBit(1)=0txtACKInt.Text=Str(Val(txtACKInt.Text)+1)IfWaitStatus(100,7,0)ThenTVicLPT1.ControlPortBit(1)=1TVicLPT1.ControlPortBit(1)=1EndIfEndSub延时或等待状态寄存器特定位的变化,SValue为0、1之外的其他数为延时功能TimeOut:延时或等待时间(ms),SNo:状态寄存器位序,SValue:期待的变化值PrivateFunctionWaitStatus(TimeOutAsSingle,SNoAsByte,SValueAsByte)DimdelayAsSingleWaitStatus=TrueResult=QueryPerformanceCounter(SysCount1)DoResult=QueryPerformanceCounter(SysCount2)delay=(SysCount2-SysCount1)/SysCountFrequency*1000'msLoopWhiledelay<TimeOutAndTVicLPT1.StatusPortBit(SNo)<>SValueIfdelay>=TimeOutThenWaitStatus=FalseEndFunction操作控制寄存器,Index为控制寄存器位序PrivateSubcmdControl_Click(IndexAsInteger)IfcmdControl(Index).Caption="0"ThencmdCont
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度智能医疗信息系统安装与维护合同
- 2024版企业vi设计合同
- 超市蔬菜称重处理方案
- 二零二四年度供应链管理与融资合同
- 2024年度某科技有限公司技术研发人员试用期劳动合同
- 二零二四年住宅小区门窗安装合同
- 超市烘焙产品定价方案
- 超市水管修理方案
- 2024版小麦铁路运输销售合同
- 超市凉席特价处理方案
- 联想绩效管理案例分析
- 医学论文投稿与评价指标
- 大学生创新创业项目商业计划书(完整)(可编辑)
- 思政示范课程-机械零部件测绘项目申报书
- 护理质控中心工作汇报
- 初中物理跨学科融合教学的实践研究
- 《高压储能变流器技术要求》
- 质保金收款收据模版
- MOOC 太极拳初级-浙江大学 中国大学慕课答案
- 电子商务论文范文大全(10篇)
- 品语言 知生活智慧树知到期末考试答案2024年
评论
0/150
提交评论