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)
页面执行时间:2.228毫秒