并行接口的分类: SPP(标准并行接口) ,EPP(增强型并行接口),ECP(扩展型并行端口)
标准并行端口(SPP)也是最早的端口定义,主要功能如下,1:并行端口提供了8个数据线以进行并行的字节传输,2:计算机能够通过数据线向打印机发送 选能信号,以通知打印机已经准备好接收数据,3:打印机招收到数据后,向计算机发送一个回应信号(NACK)。其各位信号线所代表的意义详见下表。
增强型并行端口(EPP)的出现提供了一种更高性能的连接方式,并东路向下兼容所有在此之前存在的并行接口及外设。与SPP不同之处在于原来17个信号 中的重新定义,在这17个信号中,EPP使用了其中的14个信号进行传输,握手和选通,剩下的3个信号可以由外设设计者有来自定义。
并行接口的大致结构:
并行口一般有25个引脚,其中包括8位数据线,5位打印机状态线,4位控制线.下面将对这些引脚予以详细说明:
(注:1:>出,表示由计算机发向打印机;入,表示由打印机发向计算机,
2:>低电平有效信号用上划线或星号表示(如S7*),高电平有效信号则没有上划线或星号)
引脚号
|
名称
|
数据位 | 寄存器 |
数据方向
|
定义
|
1
|
/STROBE
|
C0* |
出
|
选通信号,低电平有效信号,表明线上有数据到达.
|
|
2
|
D0
|
DATA_1-DATA_8
|
D1-D8 |
出
|
八位数据线,只有在SPP指令下才有能输出数据.
|
3
|
D1
|
出
|
|||
4
|
D2
|
出
|
|||
5
|
D3
|
出
|
|||
6
|
D4
|
出
|
|||
7
|
D5
|
出
|
|||
8
|
D6
|
出
|
|||
9
|
D7
|
出
|
|||
10
|
/ACK
|
S6 | Status |
入
|
应答,以插入低电平的形式出现,表明最后一个字符已招收完毕。
|
11
|
BUSY
|
S7*
|
Status |
入
|
繁忙通知,以插入高电平的方式出现,表明打印机处于忙状态不能再接收数据。
|
12
|
PE
|
S5 | Status |
入
|
没有打印机纸。
|
13
|
SELECT
|
S4 | Status |
入
|
选择输入,以插入高电平的方式出现,表明打印机处于在线待命状态。
|
14
|
AUTO FEED
|
C1* | Control |
出
|
自动馈送,低电平有效信号民,通知打印机对于每遇到一个回车进行自动换行。
|
15
|
/ERROR
|
S3 | Status |
入
|
错误,该信号由打印机发向计算机,表明打印机处于错误状态。
|
16
|
/INIT
|
C2 | Control |
出
|
初始化,低电平有效信号,该信号用来对打印机进行复位。
|
17
|
/SELIN
|
C3* | Control |
出
|
选择输入,低电平有效信号,表明已经选中的打印机。
|
18
|
GND
|
---
|
信号接地
|
||
19
|
GND
|
---
|
信号接地
|
||
20
|
GND
|
---
|
信号接地
|
||
21
|
GND
|
---
|
信号接地
|
||
22
|
GND
|
---
|
信号接地
|
||
23
|
GND
|
---
|
信号接地
|
||
24
|
GND
|
---
|
信号接地
|
||
25
|
GND
|
---
|
信号接地
|
下面是对打印机状态端口及打印机控制端口作一详细解释:
控制端口:
0x37A
|
1
|
1
|
输入控制
|
中断
|
17线
|
16 线
|
14 线
|
1 线
|
这个0x37A计算机控制打印机的地址,可以产生对打印机进行控制的必要信号,可写,两高位(7和8)没什么用,第6位写1表示可以向并口输出数据。第 五位中断信号(IRQ EN),利用此信号线,驱动程序可以在STATUS端口信号(nAck)的帮助下,使用该信号对中断信号的产生与否进行控制。第 3,2,1,0位分别控制第17线,第16线,第14线和第1线。(可以控制它们的状态)具体作用可参见前表
状态端口:
0x379
|
(S7)11 忙
|
(S6)10应答
|
(S5)12缺纸
|
(S4)13联机
|
(S3)15 错误
|
S2
|
S1
|
S0
|
0x379为打印机状态地址,可读,通过个端口打印机适配器可以很方便的读取打印机的状态。
标记为S7的信号表示最高位,SO表示为最低位,只有S3-S7五个信号才是真正有用的信号。他们的具体信号功能解释如下:
S7*(busy):打印机使用该信号表示打印机正处于忙状态,不能再接收数据。需要强调的是,该信号通过适配器板时,进行了反相处理,因此连接器上的低电平到微处理器时就变成了高电平。
S6(nAck):当适配器发出选通信号时,打印机就会产生该信号作为响应。通常情况下,该信号是高电平,选通打印机之后,打印机首先把该信号设为低电平,然后再返回高电平。
S5(PE):当打印机缺纸时,它就会产生一个这样的信号,通常情况下,该信号由打印机保持为低电平,打印机纸使用完之后,该信号就会变成高电平。
S4(SELECT):当打印机恢复正常操作时,它就会插入一个高电平的该信号。当打印机处于无效状态时,访信号就会变成低电平。
S3(NERROR):当打印机出现错误时就会产生这种邮错信号。产生出错的原因很多,如打印纸堵了或产生了内部错误。产生错误时该信号就会设置成低电平。
以下为在Windows CE 下打印机各种状态时,所对应的状态寄存器的(AL)的值:
1:>在没接入打印机时寄存器AL值为127,对应二进制是:1111111
2:>打印机在缺纸灯不亮时寄存器AL值为144,对应二进制是:10010000
3:>打印机在缺纸灯亮时寄存器AL值为 119;对应二进制值是:11101111
4:>打印机在不缺纸的情况下寄存器AL值 223,对应二进制值是:11011111
5:>打印机在没开机的情况下得到AH值为207,对应二进制值是:11001111
2:>打印机在缺纸灯不亮时寄存器AL值为144,对应二进制是:10010000
3:>打印机在缺纸灯亮时寄存器AL值为 119;对应二进制值是:11101111
4:>打印机在不缺纸的情况下寄存器AL值 223,对应二进制值是:11011111
5:>打印机在没开机的情况下得到AH值为207,对应二进制值是:11001111
下面介绍对并口的编程控制:
(编程控制示例)(为汇编代码)
// 此段代码为并口向打印机进行写数据,并发送控制信息。
// 此段代码为并口向打印机进行写数据,并发送控制信息。
#define LPT_CLEAR_MASK 0x40
#define LPT_STROBE_HI 0x0D
#define LPT_STROBE_LO 0x0C
#define LPT_STATUS_BITS 0xF8
#define LPT_BITS_INVERT 0x48
#define LPT_NOTBUSY 0x80
#define LPT_PAPEROUT 0x20
#define LPT_SELECT 0x10
#define LPT_NFAULT 0x08
#define LPT_TimeOut 0x01
void OutByte(ULONG dataport, BYTE databyte) {
#if x86
_asm {
mov dx, word ptr [dataport]
mov al, byte ptr [databyte]
out dx, al
out dx, al
add dx, 2
in al, dx
and al, LPT_CLEAR_MASK
mov cl, al
or al, LPT_STROBE_HI
out dx, al
out dx, al
out dx, al
out dx, al
or cl, LPT_STROBE_LO
mov al, cl
out dx, al
}
#else
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
dataport+=2;
databyte = (READ_PORT_UCHAR((PUCHAR)dataport) & LPT_CLEAR_MASK)
| LPT_STROBE_HI;
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
databyte = (READ_PORT_UCHAR((PUCHAR)dataport) & LPT_CLEAR_MASK)
| LPT_STROBE_LO;
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
#endif
}
#define LPT_STROBE_HI 0x0D
#define LPT_STROBE_LO 0x0C
#define LPT_STATUS_BITS 0xF8
#define LPT_BITS_INVERT 0x48
#define LPT_NOTBUSY 0x80
#define LPT_PAPEROUT 0x20
#define LPT_SELECT 0x10
#define LPT_NFAULT 0x08
#define LPT_TimeOut 0x01
void OutByte(ULONG dataport, BYTE databyte) {
#if x86
_asm {
mov dx, word ptr [dataport]
mov al, byte ptr [databyte]
out dx, al
out dx, al
add dx, 2
in al, dx
and al, LPT_CLEAR_MASK
mov cl, al
or al, LPT_STROBE_HI
out dx, al
out dx, al
out dx, al
out dx, al
or cl, LPT_STROBE_LO
mov al, cl
out dx, al
}
#else
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
dataport+=2;
databyte = (READ_PORT_UCHAR((PUCHAR)dataport) & LPT_CLEAR_MASK)
| LPT_STROBE_HI;
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
databyte = (READ_PORT_UCHAR((PUCHAR)dataport) & LPT_CLEAR_MASK)
| LPT_STROBE_LO;
WRITE_PORT_UCHAR((PUCHAR)dataport,databyte);
#endif
}
// 此段代码为读取打印机当前状态。
BYTE CheckStatus(unsigned port) {
BYTE bRet;
#if x86
_asm {
mov dx, word ptr[port]
Checkme:
in al, dx
mov ah, al
nop
nop
in al, dx
cmp al, ah
jnz Checkme
and ah, LPT_STATUS_BITS
xor ah, LPT_BITS_INVERT
test ah, LPT_PAPEROUT or LPT_NFAULT
jnz CS_HasError
test ah, LPT_SELECT
jz CS_HasError
and ah, LPT_NOTBUSY
jz CS_HasError
xor eax, eax
CS_HasError:
mov [bRet],al
}
#else
BYTE bStatus;
do {
bRet= bStatus= READ_PORT_UCHAR((PUCHAR)port);
} while (bStatus != READ_PORT_UCHAR((PUCHAR)port));
bStatus&= LPT_STATUS_BITS;
bStatus^= LPT_BITS_INVERT;
if (!(bStatus & (LPT_PAPEROUT | LPT_NFAULT)) &&
(bStatus & LPT_SELECT) && (bStatus & LPT_NOTBUSY))
bRet=0;
#endif
return bRet;
}
BYTE CheckStatus(unsigned port) {
BYTE bRet;
#if x86
_asm {
mov dx, word ptr[port]
Checkme:
in al, dx
mov ah, al
nop
nop
in al, dx
cmp al, ah
jnz Checkme
and ah, LPT_STATUS_BITS
xor ah, LPT_BITS_INVERT
test ah, LPT_PAPEROUT or LPT_NFAULT
jnz CS_HasError
test ah, LPT_SELECT
jz CS_HasError
and ah, LPT_NOTBUSY
jz CS_HasError
xor eax, eax
CS_HasError:
mov [bRet],al
}
#else
BYTE bStatus;
do {
bRet= bStatus= READ_PORT_UCHAR((PUCHAR)port);
} while (bStatus != READ_PORT_UCHAR((PUCHAR)port));
bStatus&= LPT_STATUS_BITS;
bStatus^= LPT_BITS_INVERT;
if (!(bStatus & (LPT_PAPEROUT | LPT_NFAULT)) &&
(bStatus & LPT_SELECT) && (bStatus & LPT_NOTBUSY))
bRet=0;
#endif
return bRet;
}