SPP信号 | EPP信号 | 方向 | EPP信号描述 |
nSTROBE | nWRITE | 输出 | 低有效,表示写操作。高电平读周期 |
nAUTOFEED | nDATASTB | 输出 | 低有效,表示数据的读写操作正在进行 |
nSELECTIN | nADDRSTB | 输出 | 低有效,表示地址的读写操作正在进行 |
nINIT | nRESET | 输出 | 低有效,外设复位 |
nIACK | nINTR | 输入 | 外设中断,用于对主机产生一个中断 |
BUSY | nWAIT | 输入 | 握手信号 ,低表示可以开始一个周期(置选通),高表示可以结束一个周期(清选通) |
D[8:1] | AD[8:1] | 双向 | 双向地址/数据线 |
PE | 用户定义 | 输入 | 每种外设有不同的使用 |
SELECT | 用户定义 | 输入 | 每种外设有不同的使用 |
nERROR | 用户定义 | 输入 | 每种外设有不同的使用 |
附图是EPP数据写周期的时序图。因它的握手信号由硬件完成,整个数据传输过程发生在一个ISA I/O周期内,因而使用EPP传送数据,协调可以获得500KB/S~2MB/S的传输率。
2.2、EPP端口及寄存器
EPP占用并行口基地址+0~+7共8个相邻的I/O映像地址。基地址+3是EPP的地址口,对它进行I/O操作便产生地址周期;基地址+4是EPP的数据口,对它进行8位I/O读写操作,便产生数据读写周期。如软件使用16位或32位的I/O操作,则会用到基地址+4~+7映像地址。对基地址+0~+2的操作与SPP相同,这就保证了与SPP的兼容性。但由于EPP为双向端口,其寄存器的内容比SPP有所增加(如表2所示)。
口地址 | 端口名 | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 |
基地址+0 | 数据口 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
基地址+1 | 状态口 | TIEMOUT | 0 | 0 | nERR | SLCT | PE | nACK | nBUSY |
基地址+2 | 控制口 | STROBE | AUTOFD | nINIT | SLC | IRQE | PCD | 0 | 0 |
基地址+3 | EPP地址口 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
基地址+4 | EPP数据口0 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
基地址+5 | EPP数据口1 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
基地址+6 | EPP数据口2 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
基地址+7 | EPP数据口3 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
新增的位如下:
(1)TIMEOUT位:逻辑“1”表示EPP读写操作时发生超时错误;逻辑“0”表示无超时发生。
(2)PCD位(Parallel Control Direction并行口方向控制):在双向传输种,PCD位为“0”时进行写操作;为“1”时进行读操作,8位数据线处于读状态。
2.3、EPP1.9和EPP1.7
EPP1.7是指Xircom 1.7版的提案,Intel在最初的82360 I/O控制器中使用这一协议,而那时IEEE1284标准还没建立起来。EPP1.7与IEEE1284标准所规定的EPP1.9的区别在于,EPP1.7在读写周期开始时,nDATASTROBE或nADDRSTROBE置位时不考虑nWAIT信号的状态。这意味着外设不能通过清nWAIT来推迟一个EPP周期的开始。因而服从1284标准的外设可以在EPP1.7的主机上工作,而EPP1.7的外设不能在服从1284 标准的主机上工作。
EPP控制芯片中的看门狗时钟会防止系统锁死。一般来讲,EPP1.9在读写周期开始10us后,如果nWAIT仍没有响应,则发生TIMEOUT错误,状态寄存器的第0位TIMEOUT为“1”,EPP周期终止;而EPP1.7则是在EPP读写周期开始10us后仍未结束时,置TIMEOUT为“1”。
3、EPP编程方法
3.1、EPP模式的设置与基地址的选择
由于EPP控制芯片的生产厂家不同,具体的编程方式也有所不同,因而EPP协议对该模式的设置和检测没有统一的规定。比较实用的设置方式是在系统的CMOS中选择含有EPP模式的选项,再选择EPP协议的类型EPP1.7或EPP1.9,由系统完成对EPP芯片的设置。
并行端口的地址也可在CMOS中设置,如果操作系统为Windows 9x,可以在其中“控制面板”的“系统”窗口中设置。值得注意的是,基地址一般使用378H或278H,而不使用3BCH。因为EPP要求8个相邻的I/O端口,而3C0H可能为VGA设备所占用。
3.2、传输方向控制
并行端口的8位数据线在EPP模式下为双向数据线,数据传输方向由控制寄存器(基地址+2)的第5位控制。该位置“1” 时,禁止数据输出,可以从外部数据线上读取信号。改位置“0”时,可以执行EPP的写操作,如地址写或数据写操作。
3.3、数据、地址的读写操作
EPP模式设置后,数据传输非常简单,只需简单的端口读写即可实现,其C语言指令如下:
写一个字节的数据:outportb(base_addr+4,data)
写一个字节的地址:outportb(base_addr+3,value)
读一个字节的数据:data=inportb(base_addr+4)
读一个字节的地址:value=inportb(base_addr+3)
3.4、状态检查及TIMEOUT位清除
每一次读写后,应检查状态寄存器是否发生错误(如超时错误TIMEOUT)。如果TIMEOUT位被置位,下一次EPP数据和地址口的读写操作都将无效,因而每次EPP操作后对该位的检测时必要的。TIMEOUT位为状态寄存器(基地址+1)的第0位,对该位TIMEOUT标志的清除,不同的控制芯片使用不同的方法,这对编程不利。有的向该位写“1”,可以清除TIMEOUT标志,写“0”对该位无影响;有的对状态寄存器进行读操作,就可以清除该位;还有的是写“0”清除该标志。所以通用的方法是读状态寄存器后,TIMEOUT位如果置位,先向该位写“1”,再写“0”。这样,无论哪种芯片都可以保证对该位的清除。
3.5、16位、32位数据的读写操作
EPP的8位数据口共有4个:基地址+4~+7,在其中任意一个端口上进行8位I/O写指令(如汇编语言的out,或C语言中的outportb函数),都会发生EPP的数据周期,与外设传递数据。这4个数据口的另一种用法是,使用16/32位输出指令,2个或4个字节就会自动的按顺序传送给外设。例如使用汇编指令outsd向第一个EPP数据口写一个双字,虽然只用了一条I/O指令,但外设收到了这双字的4个字节。值得注意的是,外设不是一次收到32位的数据,而是分4次收到,在EPP模式下,数据宽度仍是8位。另外,地址口只能使用8位I/O指令,不能一次传递 16位或32位地址。
3.6、Windows 3.x/Windows 9x环境下的编程
Windows 3.x/Windows 9x环境下对硬件操作的最好方法是使用虚拟设备驱动程序VxD(virtual device driver),它可以使用DDK或C开发,对端口的操作可以得到系统级的保护,并能得到快速的中断响应。另一种和硬件打交道的方法是使用OCX或ActiveX控件,在32位的Visual Basic中就能实现。但是这些方法需要较多的编程经验,所采用的编程语言也受到很大限制,一般的软件人员不易实现。使用 Windows API也可以实现硬件操作,例如通过API调用可以实现对串口和打印机的操作。但是Windows API没有一般性的端口操作函数,不适用于 EPP的编程。
实用而有效的方法是对EPP进行直接I/O操作,并将相关函数生成动态连接库DLL,供应用程序调用。在并口不被其他程序使用的情况下,对EPP执行直接I/O读写是没有问题的。由于Windows编程语言都支持对DLL的调用,因而程序员可以使用他所熟悉的语言(包括不支持直接I/O的VB)编写应用程序,实现EPP的操作。
下面给出在32位的Delphi中,通过内嵌汇编代码实现的EPP端口读写的input32.dll源程序。
library input32;
uses sysutils;
//向端口写一个字节
procedure function out32(portaddress, value: smallint);stdcall;export;
var
bytevalue: byte;
begin
bytevalue := byte(value);
asm
push dx
mov dx,portaddress //写bytevalue到portaddress
mov al,bytevalue
out x,al
pop dx
end; end;
//从端口读一个字节,br> function in32(portaddress: smallint):smallint;stdcall;export;
var
bytevalue: byte;
begin
asm
push dx
mov dx,portaddress //从portaddress读bytevalue
in al,dx
mov bytevalue,al
pop dx
end;
in32 := smallint(bytevalue) and $00ff;
end;
exports
in32,out32;
begin
end.
文章评论(0条评论)
登录后参与讨论