Electronics 版 (精华区)
发信人: dongyun (冬云), 信区: Electronics
标 题: EPP编程
发信站: 哈工大紫丁香 (2001年04月28日09:52:59 星期六), 站内信件
发信人: leu1 (Joe), 信区: Circuit
标 题: EPP编程
发信站: BBS 水木清华站 (Fri Apr 20 18:06:47 2001)
EPP编程
由于EPP(IEEE1284标准)是最近新出的标准,因此虽然很多厂商声称支持
EPP,但
是实际上众多厂商生产的产品并不兼容。所以很难有一种通用的程序,适用于所有
的产
品,这就使EPP编程变得异常困难。以下是一些常见的问题和解决方法。
* 在EPP模式下,可以直接设置Control寄存器的bit5位,使EPP端口进入读状态。
而ECP
+EPP模式下是使用ECP仿真EPP模式。以Award的BIOS为例,在ECP+EPP模式下,因为
无法
设置Control寄存器的bit5(Read Enable)位(即无法使端口变为读状态),因此读写
LPT+
3和LPT+4端口操作无效。此时必须先设置ECP的ECR寄存器(base+402H,例如
base=378H,则
ECR=77aH) bit7,6,5。设置模式如下:
000 SPP
001 Byte
010 Fast Centronics
011 ECP
100 EPP
101 Reserved
110 Test
111 Config
将ECR设置成'100'(即EPP模式),然后在将Control寄存器的bit5置1,端口进入
读状态
将ECR设置成'100'(即EPP模式),然后在将Control寄存器的bit5置1,端口进入
读状态
,此时即可对378H, 37bH, 37cH进行读操作;清除Control寄存器的bit5,即可对
378H,
37bH, 37cH进行写操作。例如:
C:\>debug
—i 77a ;查看ECR内容
15 ;高三位为‘001’即处于Byte模式
—o 77a 34 ;输出34H
—i 77a ;
35 ;读出却是35H,说明bit0是只读的,证明确实处于ECP模式
—o 77a 95 ;写入95H,即高三位为‘100’,进入EPP模式
—i 77a ;
95 ;读出95H,说明已进入EPP模式
—i 37a ;读Control寄存器
CC ;bit5=0
—o 37a e4 ;bit5置1,端口进入读状态
—i 37a ;
E4 ;确认bit5=1,端口进入读状态
—i 378 ;此时若2,9脚接地,则378H, 37bH,37cH都应读出7EH
7E ;
—i 37b ;
7E ;
—i 37c ;
7E ;
7E ;
* 要想检验并口的模式、端口状态、读写端口等,最好的方法是使用DOS命令:
DEBUG。
例如:
C:\>debug
—i 378 ;读入DATA寄存器内容
04 ;内容为04H
—o 378 aa ;向DATA端口写入aaH
—i 378
AA ;DATA寄存器内容变为AAH
—i 379 ;读入状态寄存器内容
7F ;如果发生Timeout,则bit0=1(SMC,AWARD芯片有此功能)
—o 379 1 ;向状态寄存器写入1,可清除bit0
—i 379
7E ;bit0被清除
—i 37a ;读出控制寄存器内容
CC ;控制寄存器bit5=0 (Port Read disable)
—o 37a ec ;bit5置1
—i 37a
EC ;bit5被置1(只有在CMOS设为EPP模式时才起作用,否则bit5无法被设置)
—i 378 ;Port Read enable后,外部总线悬浮,电平为高
FF
—i 37b ;读EPP的DATA寄存器(如果此时外部有输入信号,它就可以读出来)
—i 37b ;读EPP的DATA寄存器(如果此时外部有输入信号,它就可以读出来)
FF
—i 37c ;读EPP的ADDRESS寄存器
FF
* EPP是一种软件密集型读写模式,即它可以用一条指令(一个ISA指令周期)实现端
口的
读写,在汇编语言中指令为INP, OUTP(输入/输出一个字节)。在C语言中用
inportb()和
outportb()。且在读写过程中,nDataStrobe, nAddressStrobe和nWrite脚会发生
相应的
变化。
例如:
void EPPReadByte(unsigned short addr,unsigned short *data)
{
……
LPT=0x378;
Status=LPT+1;
Control=LPT+2;
EPPAddr=LPT+3;
EPPData=LPT+4;
/*输出地址*/
outportb(Control,0xC4); /*Disable Port Read,以及初始化nDataStrobe,
nAddre
ssStrobe*/
/*和nWrite */
outportb(EPPAddr,addr);/*Output address to address register,此时
nAddressSt
robe*/
robe*/
/*和nWrite管脚变为低电平*/
outportb(Status,1); /*确保Status寄存器的bit0清除*/
/*读入数据*/
outportb(Control,0xE4); /*Enable Port Read*/
*data=inportb(EPPData);/*读入数据,此时nDataStrobe变为低电平nWrite为高
电平
*/
outportb(Status,1); /*确保Status寄存器的bit0清除*/
}
* 由于各厂家的产品不完全兼容,因此EPP端口的初始化显得非常重要。EPP初始化
需要
注意以下几个问题:
(1)如何设置EPP模式:一般CMOS中对并口设置会有以下几个选项:SPP(
DEFAULT)、
EPP、ECP、ECP+EPP。一般而言为防止EPP同Windows发生冲突,推荐选用ECP+EPP模
式(E
CP模式是Microsoft提出的)。但是在ECP+EPP下是用ECP模拟EPP,需要在程序中设
置EC
R寄存器的高三位为‘100’(EPP模式),否则你无法设置Control端口的bit5,(即
无法读
数据)。
因此在使用EPP之前,必须判断端口处于哪种工作模式:可通过判断ECR寄存器
bit0是否
是只读的来判断是否处于ECP模式,如果ECR的bit0是只读的,则处于ECP模式;如
果Con
trol寄存器的bit5是只读的,则不是处于EPP模式。
(2)Control端口的初始化:为确保正确对端口进行读写操作,必须对Control端
口进行
初始化。主要是对bit5, nDataStrobe, nAddressStrobe, nWrite等4位进行初始化
。bi
t5置1使数据端口对外呈现高阻态,这时可以对端口进行读操作;反之可对端口进
行写操
作。同时nDataStrobe, nAddressStrobe, nWrite等脚应为高电平,但是因为这几
位在C
作。同时nDataStrobe, nAddressStrobe, nWrite等脚应为高电平,但是因为这几
位在C
ontrol寄存器中为反转位,因此应该置0。总之Control=0xE4(或0x24)表示读状态
(Cont
rol=XX100100);Control= 0xC4(或0x04)表示写状态(Control=XX000100)。
(3)Status端口的初始化:首先硬件应保证nWait为低电平,当nDataStrobe或
nAddres
s有效时(即变为低电平时),nWait应变为高电平,然后再变为低电平(否则会产生
超时错
误,Status的bit0被置1)。这可以用一个与非门来实现:nDataStrobe和
nAddressStrobe
为与非门的输入,nWait为与非门的输出。另外,为确保在出现Timeout错误时,系
统不
至于进入死循环,许多厂商用硬件实现了一个Watchdog,出现Timeout错误时
(>10us未收
到nWait下降沿信号),将Status的bit0置1。但有时读写开始时,Status的bit0就
是1。
为确保正确读写, Status的bit0必须被清除,清除方法也各不相同。有的只要执
行inp
ort(Status)就可以将bit0清除;有的要执行outportb(Status,1)才能将bit0清除
。
(注:清除Status的bit0并不是必须的,只是为了确保万无一失。有时即便
Status的bi
t0是1,也可以正确读写端口。)
* EPP BIOS编程:早期,EPP BIOS标准(IEEE1284.3)刚出时,很多厂家都支持
EPP BIOS
。但是由于EPP BIOS标准本身并不完善,再加上真正使用EPP BIOS的产品极少,因
此现
在不少厂家的BIOS中没有写入EPP功能(即int 17的AH=0020功能)。这种状态以后
可能
会有改观。
综上所述给出使用EPP进行读写的例程:
#include"dos.h"
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
typedef unsigned short BYTE;
typedef unsigned short BYTE;
void EPPBegin(int);
void EPPReadByte(BYTE,BYTE*);
void EPPWriteByte(BYTE,BYTE);
void EPPEnd(void);
int LPT,Status,Control,Address,Data,ECR;
BYTE OldECR;
void EPPBegin(int LPTn)
{
int offset;
BYTE value1,value2;
switch(LPTn)
{
case 1: offset=0x08;break; /* offset of LPT1*/
case 2: offset=0x0a;break; /* offset of LPT2*/
case 3: offset=0x0c;break; /* offset of LPT3*/
}
LPT=peek(0x40,offset);
if(LPT==0)
{
printf("Sorry, on this machine LPT%d does not exist\n",LPTn-'0');
getch();
exit(0);
exit(0);
}
Status=LPT+1;
Control=LPT+2;
Address=LPT+3;
Data=LPT+4;
ECR=LPT+0x402;
printf("\nLPT%d detected!\n",LPTn);
printf("DATA port is %xh\n",LPT);
/* printf("STATUS port is %xh\n",dport+1);
printf("CONTROL port is %xh\n",dport+2);
printf("EPP ADDRESS port is %xh\n",dport+3);
printf("EPP DATA port is %xh\n",dport+4);*/
OldECR=inportb(ECR);
outportb(ECR,0x34);
if(inportb(ECR)!=0x35)
printf("\nNot ECP mode!");
else
{
outportb(ECR,0x95); /* Enable EPP mode under ECP mode */
}
outportb(Control,0xe4); /* Set bit5 of Control Port */
if(inportb(Control)&0x20!=0x20) /* If bit5 is readonly */
if(inportb(Control)&0x20!=0x20) /* If bit5 is readonly */
{
printf("\nControl=%xH\nCan't enable read port!",inportb(Control));
printf("\nPlease config the CMOS and setup EPP mode first!");
getch();
exit(0);
}
}
void EPPReadByte(BYTE addr,BYTE* x)
{
/* Write addr */
outportb(Control,0xc4); /* disable Read port*/
outportb(Address,addr);
if(inportb(Status)&0x01==1)
{
printf("\nStatus bit0=1, Timeout Error!");
outportb(Status,1); /* Clear bit0 of Status port*/
}
/* Read byte */
outportb(Control,0xe4); /* Enable Read port */
*x=inportb(Data);
if(inportb(Status)&0x01==1)
{
{
printf("\nStatus bit0=1, Timeout Error!");
outportb(Status,1); /* Clear bit0 of Status port*/
}
}
void EPPWriteByte(BYTE addr,BYTE x)
{
/* Write addr */
outportb(Control,0xc4); /* disable Read port*/
outportb(Address,addr);
if(inportb(Status)&0x01==1)
{
printf("\nStatus bit0=1, Timeout Error!");
outportb(Status,1); /* Clear bit0 of Status port*/
}
/* Write byte */
outportb(Data,x);
if(inportb(Status)&0x01==1)
{
printf("\nStatus bit0=1, Timeout Error!");
outportb(Status,1); /* Clear bit0 of Status port*/
}
}
}
void EPPEnd(void)
{
outportb(ECR,OldECR);
outportb(Control,0xCC);
}
void main()
{
BYTE i,a[8];
clrscr();
EPPBegin(1);
for(i=0x00;i<8;i++)
{
EPPReadByte(i,&a[i]);
printf("\na[%d =%d",i,a[i]);
}
EPPEnd();
getch();
}
--
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.113.2.136]
--
心如湖水,波澜不惊
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: es.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:5.366毫秒