本章先介绍接口的基本知识,接着介绍可编程并行接口芯片8255A。后面几章将重点讨论其它几种常用可编程I/O接口芯片的工作原理、编程方法以及这些芯片如何与CPU和外设相连等问题。
计算机与外设之间交换数据、状态和控制命令的过程统称为通信(Communication)。CPU与外设交换信息的过程,和它与存储器交换数据那样,也是在控制信号的作用下通过数据总线来完成的。
存储器芯片的存取速度与CPU的时钟频率在同一数量级,存储器本身又具有数据缓冲能力,所以CPU与存储器可以很方便地交换数据,但与外设交换数据的过程要复杂得多。
计算机与外设间的信息交换存在的问题:
MAX232
和 MAX233
等芯片来实现电平转换,在第9章讨论。可见,I/O接口电路是外设与计算机之间传送信息的交接部件,它在两者间起协调作用,每个外设都要通过接口电路才能与主机相连。
随着VLSI技术的发展,出现了许多通用可编程接口芯片,可利用它们方便地构成接口电路。
CPU与外设通信时,主要传送数据信息、状态信息和控制信息。在接口电路中,这些信息分别进入不同的寄存器,通常将这些寄存器和它们的控制逻辑统称为I/O端口(Port),CPU可通过数据总线、地址总线、控制总线对端口(接口电路中的寄存器)中的信息直接进行读写。
(端口就是寄存器!)在一般接口电路中都要设置以下几种端口.
数据端口
数据端口(Data Port)或数据口,用来存放外设送往CPU的数据,或者CPU要输出到外设去的数据,长度一般为 1~2
字节。数据口主要起数据缓冲作用。
状态端口
状态端口(Status Port)指示外设的当前状态。每个外设具有几个状态位,它们可由CPU读取,以测试或检查外设的状态,决定程序的流程。状态口中常用的状态位:
1
表明端口的数据寄存器已准备好数据,等待CPU来读取;当数据被取走后,该位清 0
。1
表明端口中的输出数据寄存器已空,可以接收CPU的下个数据了;当新数据到达后,这位便清 0
。ready
位一般不会同时出现。1
,表示外设正在进行I/O传送操作,暂时不允许CPU送新的数据过来。0
,表示外设已处于空闲状态,又允许CPU将下一个数据送到输出口。1
,以便CPU进行相应的处理。命令端口
命令端口(Command Port)也称为控制端口(Control Port),用来存放CPU向接口发出的各种命令和控制字,控制接口或设备的动作。
只存在一个内存系统,把系统中每个I/O端口都看作1个存储单元,并与存储单元统一编址,所有访存指令均可用来访问I/O端口,不用设置专门的I/O指令,如下图所示。
如Motorola公司的 MC6800、MC68000、MC6805
等CPU,采用这种寻址方式。
统一编址也称为存储器映射编址方式,是把每一个端口视为一个存储单元,I/O端
口与存储单元在同一个地址空间中进行编址,如图所示。
对系统中的输入输出端口地址单独编址,不占用存储空间,而用专门的 IN/OUT
指令来访问。
IN
和 OUT
指令,其功能没有访存指令强;CPU需提供能够区分访问内存和访问I/O的硬件引脚信号。在 8086/8088
系统中都采用I/O寻址方式。如 IN AL, 端口地址/DX
(必须是 AL
) 和 OUT 端口地址/DX, AL
(必须是 AL
) 。
今天的PC机系统,是统一编址和单独编址同时使用的,其中,INTEL很早(80年代初)就抛弃了单独编址,只是为了兼容以前的设备,才不得不同时使用两种方式。
1.程序控制方式(软件):数据传送在程序控制下完成,又可分为无条件传送和条件传送两种方式。
2.中断方式(软件) :外设发中断请求,CPU响应后完成数据传送。
3.DMA方式(硬件):DMA控制器临时接管CPU的地址、数据和控制总线,实现批量数据的传送。
PC机中,中断控制、DMA控制、动态RAM刷新、系统配置识别、键盘代码读取及扬声器发声等都是由可编程I/O接口芯片控制的。
接口芯片包括:中断控制器8259A、DMA控制器8237A-5、并行接口芯片8255A-5、计数器/定时器8253-5等,都要使用I/O端口地址。
除键盘、显示器、打印机、磁盘驱动器等常规外设,在系统板上还有8个I/O扩展槽,可在槽中插入I/O适配器,即扩展卡,提供数据采集卡、通信卡等其它外设接口,它们也需用I/O端口地址。系统统一安排这些端口的地址。
PC/XT 机系统中,使用低10位地址(A9~A0
)寻址I/O端口,I/O地址空间占1K。当 A9=0
时,寻址系统板上的 512
个端口;当 A9=1
时,寻址I/O通道上的 512
个端口。
系统板和I/O通道上的I/O端口地址分配见表6.1。表中,系统板(相当于分成了八间房)地址含两部分,前面是译码电路生成的地址,而括号中是I/O接口芯片实际使用的地址。
系统板上I/O端口译码电路中,各接口芯片的片选信号由 74LS138
译码电路产生,在CPU控制系统总线时,AEN'=1
,这时若 A9A8=00
,则译码器选通,对输入 A7A6A5
译码,在 Y 0 ‾ \overline {Y_0} Y0 ~ Y 7 ‾ \overline {Y_7} Y7 中产生一个低电平输出信号,接到相应接口芯片的 CS ‾ \overline {\text{CS}} CS 端或控制端。
电路在I/O读写命令控制下工作。I/O地址的低4位 A3~A0
用作控制芯片内部寄存器的选择信号,这样每个译码输出端都包含 2 4 = 16 2^4=16 24=16 个端口地址。
16
个寄存器,例如 8237A DMA
控制器,使用 00-0FH
共 16
个端口地址。16
个寄存器,如 8259A
只有 2
个寄存器,8253-5
和 8255A
各有 4
个寄存器,较高位地址可以不用,仅用 A1
和 A0
等低位地址选择端口。8259A占用的端口地址范围为 020H-03FH
,但实际只用到最低2个端口地址 20H
和 21H
,而 NMI
屏蔽寄存器仅用了 1
个I/O地址 A0H
。
以 80286
为CPU的 PC/AT
机中,也只使用低10位地址进行I/O端口地址的译码。
地址范围 000~3FFH
,但使用两片 8237A-5 DMA
控制器,两片 8259A
中断控制器,定时器使用 8254-2
。PC/AT
及其兼容机的I/O端口地址分配如表。
8255A是一个通用可编程并行I/O接口的芯片,是Intel的CPU配套电路,常用于数据的输入和输出,可工作于3种不同的数据传输方式。
事实上,8255A一直保留到今天,如果打开设备管理器,就会发现,键盘的资源中有一个端口是 60H
,系统设备中扬声器也有一个端口 61H
,它们分别是8255A的A口和B口。
外部 40
个引脚。内部包含:
A、B、C
。其中,C口分成C口上半部(C高)和C口下半部分(C低)。PA7~PA0
和 PB7~PB0
、PC7~PC4
、PC3~PC0
,可以做以字节为单位的数据传输。数据端口A、B和C
8
位的数据输出锁存器/缓冲器,1个 8
位的数据输入锁存器。A口作输入或输出时数据均能锁存。8
位的数据输入/输出锁存器/缓冲器,1个8位的数据输入缓冲器。8
位的数据输出锁存器/缓冲器,1个 8
位的数据输入缓冲器,无输入锁存功能(数据送过来,C口中的状态会立即改变
),分成两个 4
位端口时,每个端口有1个 4
位的输出锁存器。A组和B组控制逻辑(不重要)
PA7~PA0
以及 PC7~PC4
引脚与外部联络。PB7~PB0
以及 PC3~PC0
引脚与外部联络。数据总线缓冲器(不重要)
8
位数据总线 D7~D0
,接收CPU送来的数据信息或控制字;外设传送给CPU的数据或状态信息,也要通过数据总线缓冲器和 D7~D0
送给CPU。读/写控制逻辑(有关信号):
RESET
,系统复位。高电平时使控制字寄存器清0,各端口工作于输入方式。
CS ‾ \overline {\text{CS}} CS 片选。译码电路产生,低电平时芯片才选中。
RD ‾ \overline {\text{RD}} RD 读。有效时,可读取8255A的数据或状态信息。
WR ‾ \overline {\text{WR}} WR 写。有效时,可向8255A写入数据或控制字。
A1A0
,端口选择。
A1A0=00
,A口; A1A0=01
,B口;A1A0=10
,C口; A1A0=11
,控制口。A1A0
与地址总线 A1A0
相连。若8255A端口基地址为60H,则A口、B口、C口和控制口分别为 60H,61H,62H和63H
。 CS ‾ = 0 \overline {\text{CS}} =0 CS=0,8255A可进行读/写操作。 RD ‾ = 0 \overline {\text{RD}}=0 RD=0 ,可从 A口、B口、C口
读出数据。 WR ‾ = 0 \overline {\text{WR}}=0 WR=0 ,可向这3个端口和控制字寄存器(只写)写入数据。口地址由 A1A0
选择, 但当 A1A0=11
时,只能向控制口写入控制字,否则为非法操作。
RD ‾ \overline {\text{RD}} RD 和 WR ‾ \overline {\text{WR}} WR 不能同时为0。
设计电路时要注意:(现实情况没有这么操作)
在 16
位数据总线的 8086
系统中,可将地址总线的A2A1
连到8255A的 A1A0
端。若它的数据线 D7~D0
接在CPU数据总线的低 8
位上,则要用偶端口地址来寻址8255A;而当 D7~D0
接在数据总线的高8位上时,要用奇地址口。
例如:若8255A的基地址为 F0H
,则
A2A1=00
,选A口,即口地址F0H;A2A1=01
,选B口,口地址F2H;A2A1=10
。选C口,口地址F4H;A2A1=11
,选控制字寄存器,口地址F6H。写入控制口以定义各端口工作方式,且要求 D7=1
。
D6D5
:选择A口的工作方式(方式 0~2
)。D2
:选择B口的方式(方式 0~1
)。C口无所谓方式。(A和B口通常是用于连接数据的,而C口往往是连接控制信号的,典型用法不一致)D4D3D1D0
:A口、C高、B口、C低的I/O方式。1-In
(输入),0-Out
(输出),可有16种组态。方式选择控制字显然是用于初始化的。
例6-1 要把A口指定为方式1,输入,C口上半部定为输出;B口指定为方式0,输出,C口下半部指定为输入。
则工作方式命令代码是 10110001B
(1_01_1_0_0_0_1
) 或 B1H
。设8255A控制字寄存器端口地址为 303H
。初始化的程序段为:
MOV DX,303H ;8255A命令口地址,超过了8位,用DX
MOV AL,0B1H ;初始化命令;要加0
OUT DX,AL ;送到命令口
为端口C特制的指令!因为C口往往是用于连接控制信号的,所以必须能够对C口的任一引脚进行置1和清0。注意:任意值我们约定必须为0!
设8255A口地址为 60H~63H
,PC5
平时为低电平,要求从 PC5
输出一个正脉冲(平时为低电平,现在拉高,然后重新回到低电平),程序段:
MOV AL, 00001011B ;先输出一个高电平
OUT 63H, AL
MOV AL, 00001010B ;然后置为低电平, 就是一个正脉冲
OUT 63H, AL
例6-2 若要把C口的 PC2
引脚置成高电平输出,则命令字应该为 00000101B
或 05H
。程序段为
MOV DX,303H ;8255A命令口地址
MOV AL,05H ;使PC2=1的控制字
OUT DX,AL ;送到命令口
8255A可工作于3种方式:
基本输入输出( Basic Input/Output
)方式,适用于不要用应答信号的简单I/O。
例如,设8255A的控制字寄存器的口地址为 63H
,若要求A口和B口工作于方式0,A口、B口和C口高4位作输入,C口低4位为输出,可用下列指令来设置:
MOV AL, 10011010B ;1_00_1_1_0_1_0
OUT 63H, AL
选通输入/输出( Strobe Input/Output
)方式。是学习的难点。
A口、B口作数据口,均可工作于输入或输出方式,并能锁存数据。要在联络信号控制下才能工作。
PC0~PC2
,PC3~PC5
用作联络(Handshaking
)信号。
A口和B口都工作于选通输入方式时,PC0-PC2, PC3-PC5
有选择地用作联络信号,PC6, PC7
还可作输入输出用。
A口为输入,PC3-5
作联络信号。控制字的 D3
位为C高I/O——D3=1
,PC6,7
为输入;D3=0
,PC6,7
为输出。对应的A口方式1输入控制字:1_01_1_1/0_x_x_x
。
B口为输入,PC0-2
作联络信号。对应的B口方式1控制字:1_xx_x_x_1_1_x
。
注意,现在对 PC3-5
或 PC0-2
这几个引脚进行方式控制字或者用置位复位控制字,不起作用,它们现在服从方式1——选通输入方式的协定,其中 PC4,PC2
的引脚和寄存器彻底脱钩;我们无法影响它们,但是可以读取除了 PC4,PC2
之外的引脚的信号高低。PC6-7
没有被绑架,它们仍服从于方式控制字的初始化命令。
选通输入联络信号:
STB ‾ \overline {\text{STB}} STB (Strobe
),选通信号。低电平时,将外部输入数据通过 PA7~PA0
(A口)或PB7~PB0
(B口)打入所选端口的输入缓冲器中。
PC4
引入该选通信号;PC2
引入该选通信号。 IBF \text{IBF} IBF(Input Buffer Full
),输入缓冲器满信号。高电平时,表示输入设备送来的数据已送到输入缓冲器中,通知外设不要送新数据来。
PC5
输出;PC1
输出。 INTE \text{INTE} INTE(Interrupt Enable
),内置的中断允许信号。
在A组和B组控制逻辑中,设有中断请求触发器 INTE A、INTE B
。只有用软件才能使其置1或清0。用置位复位字使 PC4
(PC寄存器的第4位变成中断允许位,PC引脚的第4位被绑走了,两者脱钩)置1时,允许A口中断;使 PC2
(PC寄存器的第2位变成中断允许位,PC引脚的第2位被绑走了,两者脱钩) 置1时,允许B口中断。
INTR \text{INTR} INTR(Interrupt Request
),是8255A向CPU发的中断请求信号。
只有当 STB ‾ \overline {\text{STB}} STB 、 IBF \text{IBF} IBF、 INTE \text{INTE} INTE 都高时,才能将 INTR \text{INTR} INTR 置为有效高电平。表示选通信号已结束,缓冲器中已有数据,中断是允许的,8255A可向CPU发中断请求信号 INTR \text{INTR} INTR ,要求CPU读取外设送到缓冲器中的数据。
方式1选通输入时序:
① 外设把1个数据送到A口或B口后,向8255A发选通信号,数据被8255A锁存。
② 随后(8255A) IBF \text{IBF} IBF 变高,指示输入缓冲器已满,外设不要送新数据来。
③ STB ‾ \overline {\text{STB}} STB 恢复高电平后,若 IBF \text{IBF} IBF 和 (8255A) INTE \text{INTE} INTE 也同时为高, (8255A) INTR \text{INTR} INTR 就会变高,请求中断,CPU响应中断后执行 IN
指令读取数据( (CPU) RD ‾ \overline {\text{RD}} RD 变低)。
④ RD ‾ \overline {\text{RD}} RD 有效后,经 tRIT
时间 INTR \text{INTR} INTR 变低,清除中断。
⑤ 读信号结束,数据读入累加器;之后 IBF \text{IBF} IBF 变低,缓冲器已空,外设可再送新的数据来。
A口输出: PC3,PC6
和 PC7
作A口的联络信号(不再服从方式控制字的设定)
B口输出: PC0,PC1
和 PC2
作B口的联络信号(不再服从方式控制字的设定)
PC4、PC5
可作输入或输出,D3=1
,输入;D3=0
,输出
选通输出联络信号:
OBF ‾ \overline {\text{OBF}} OBF (Output Buffer Full
) , 输出缓冲器满。
PC7
用作 OBF A ‾ \overline {\text{OBF}_A} OBFA ,PC1用作 OBF B ‾ \overline {\text{OBF}_B} OBFB ACK ‾ \overline {\text{ACK}} ACK (Acknowledge
) ,外设回答信号,CPU输出到A口或B口的数据已被外设接收。PC6
用作 ACK A ‾ \overline {\text{ACK}_A} ACKA ,PC2
用作 ACK B ‾ \overline {\text{ACK}_B} ACKB 。
INTE \text{INTE} INTE ,中断允许信号,INTE=1
,端口允许中断,置0时被屏蔽。 INTE A \text{INTE}_A INTEA 由 PC6
控制, INTE B \text{INTE}_B INTEB由 PC2
控制,它们由置位/复位字进行设置。
INTR \text{INTR} INTR ,中断请求信号
=1
时,才能使 INTR \text{INTR} INTR 变高。 INTR A \text{INTR}_A INTRA从 PC3
引脚输出, INTR B \text{INTR}_B INTRB 从 PC0
输出。方式1选通输出时序
① CPU响应中断后,执行 OUT
指令输出数据, WR ‾ \overline{\text{WR}} WR 变低
② 经 t W I T t_{WIT} tWIT 时间后,清除中断请求信号,使 INTR = 0 \text{INTR}=0 INTR=0
③ WR ‾ \overline{\text{WR}} WR 的后沿使 OBF ‾ = 0 \overline {\text{OBF}}=0 OBF=0 ,通知外设从输出缓冲器中取走数据
④ 外设收到数据后,发回应答信号, ACK ‾ = 0 \overline {\text{ACK}}=0 ACK=0
⑤ 应答后再经 t A O B t_{AOB} tAOB, OBF ‾ \overline {\text{OBF}} OBF 无效,指示缓冲器已空
⑥ ACK ‾ \overline {\text{ACK}} ACK 回到高电平后,经 t A I T t_{AIT} tAIT 时间, INTR \text{INTR} INTR 变高,向CPU发中断请求,让CPU再送一个新数据过来
A口输入,B口输出
PC0~PC5
作控制线D3=1
,PC6、7
为输入D3=0
,PC6、7
为输出A口输出,B口输入
PC0~PC3
和 PC6、PC7
作控制D3=1
,PC4、5
为输入D3=0
,PC4、5
为输出方式2也称为双向总线方式,只有A口支持方式2。A口既能用作输入口,也可以编程为输出口,与外设双向交换数据。
双向数据都能被锁存。
(1)工作方式2 只适用于A口,B口仍按方式0或方式1工作。
(2) A口可工作于双向方式,C口的 PC7~PC3位作为A口 的控制/状态信号端口, PC2~PC0用于B组 。
(3)A口的输入/输出均有锁存功能。在方式2工作状态下,A口既可工作于查询方式,又可工作于中断方式。
PC3~PC7
作A口的联络信号:
输入: STB A ‾ \overline {\text{STB}_A} STBA , ACK A ‾ \overline {\text{ACK}_A} ACKA
输出: OBF A ‾ \overline {\text{OBF}_A} OBFA , IBF A \text{IBF}_A IBFA, ACK A ‾ \overline {\text{ACK}_A} ACKA , INTR A \text{INTR}_A INTRA
原理与方式1的A口选通输入、A口选通输出类同
方式1和2时,C口用作联络信号。用 IN
指令读取C口内容可检测外设状态,这样, 就可采用查询方式而不用中断方式实现数据交换。
1)方式1
(输入或输出)状态字
D7~D3
位为A组状态字,D2~D0
位为B组状态字。
2)方式2
状态字
D7~D3
位:A组状态字
D2~D0
位:
1)要求: 查询方式,打印首址为 BUF
的 256
个字符(ASCII码)
2)使用的信号(Centronics标准,8位并行)
BUSY
:忙,=1
,打印机忙;打印机打印完使 BUSY=0
,可供查询DATA BIT1~8
( DB1~8
):数据线,传送字符的ASCII码,但数据并未进入打印机DB1~8
上的数据打入打印机内PA
方式0,输出; P C 上 PC_上 PC上 输入, P C 下 PC_下 PC下 输出;方式字:88H
完成初始化后,先将 DSTB ‾ \overline {\text{DSTB}} DSTB 置为1,使其无效(
0_000_001_1=03H
)
内存中有一个buf
,SI
指向buf
,然后循环次数为256
;
每次输出前先检查打印机的状态,看302H
端口的PC
状态,检查其第5
位的状态是否忙,and al, 20H
,busy=0
时循环等待;
busy=1
,将SI
指向的数据送上300H
端口,然后用置位控制字0_000_001_0
将PC1
置为0
选通打印机;等待一段时间,用nop
指令;
之后,用置位控制字0_000_001_1
,再让PC1
为1
,令其失效。
这个程序体现的是数据传输中典型的查询方式。缺点在于CPU在这个过程中处于繁忙的状态,好处在于程序结构简单,常用于单片机。
1)要求:甲机向乙机传送 1KB
,甲方式1;乙方式0,查询方式,设 M
首址分别为 SRC、DST
2)硬件设计:甲有固定联络线,乙没有
甲机:PA
口方式1,输出(绑架367
引脚),方式字=0A0H
(1_01_0_0_00_0
,PB
没用,PC
有的引脚被方式1绑定,不管)
乙机:PB
口方式0,输入,PC上输出,PC下输入,方式字=83H
(1_00_0_0_0_1_1
)
说明:传送过程由甲机启动,写入数据,等待中断
甲机发送条件:INTR=1
(INTE=1
,PC6
中断允许位)
乙机接收条件:对方(甲机)的 OBF=0
甲发送程序段:(用到了芯片的中断机制,但是实质仍然是查询方式)
MOV DX,303H
MOV AL,0A0H ;方式字
OUT DX,AL
MOV AL,0DH ;INTEA=1 0_000_110_1
OUT DX,AL
LEA SI,SRC ;循环准备
MOV CX,1024 ;1024字节
MOV DX,300H ;PA写第一个数
MOV AL,[SI]
OUT DX,AL
INC SI ;指向下一个数
DEC CX ;循环次数减1
L: MOV DX,302H ;读PC寄存器
IN AL,DX
AND AL,08H ;保留第5位0000_1000
JZ L ;中断不允许,继续循环
MOV DX,300H ;写数
MOV AL,[SI]
OUT DX,AL
INC SI
LOOP L
乙接收程序段
MOV DX,303H
MOV AL,83H
OUT DX,AL ;设置方式字
MOV AL,0BH
OUT DX,AL ;PC5置为1,ACK为无效
LEA DI,DST ;准备目的串
MOV CX,1024 ;准备循环
L: MOV DX,302H ;大循环
IN AL,DX ;检查OBF
AND AL,02H
JNZ L ;对方OBF=0? 不等于继续循环
MOV DX,301H ;PB端寄存器
IN AL,DX ;读入内容
MOV [DI],AL ;存放1个数据
MOV DX,303H ;控制字寄存器
MOV AL,0AH ;发送应答信号
OUT DX,AL
NOP
NOP
MOV AL,0BH ;置ACK为无效
OUT DX,AL
INC DI
LOOP L
甲发送程序段 - 2
data segment
message db 0
src db 1024 dup (?)
data ends
code segment
assume cs: code, ds: data
start: mov dx, 303h
mov al, 0a0h
out dx, al
mov al, 0dh
out dx, al
cli ;注册为中断服务程序
xor bx, bx
mov es, bx
mov bx, 0FH * 4
mov dx, offset int_svr
mov es:[bx], dx
mov dx, seg int_svr
mov es:[bx+2], dx
sti ;这一段代码
lea si, src ;循环准备
mov cx, 1024
output: mov dx, 300h ;数据送到PA口
mov al, [si]
out dx, al ;输出数据
inc si
wait: cmp message, 1 ;检查有没有消息
jnz wait ;没消息,等待
mov ax, 0
mov message, ax ;有消息,清0
loop output ;继续送下一份消息
;wait以下的5句可以改造成:
;HLT ;不用循环进行忙等待,而是用HLT指令
;cmp message,1
;jnz wait
;mov message, 0
;loop output
code ends
end start
;中断服务程序
code2 segment
int_svr:
push ax ;用到了ax,dx入栈
push dx
mov dx, 302h ;读入PC口
in al, dx
and al, 80h ;判断PC7
jz exit
mov message, 1 ;OBF!=零,核心,message置1发消息,意味着可以发下一个数据
exit:
mov al, 20h ;EOI ;忽略
out 20h, al ;忽略
pop dx
pop ax
iret
code2 ends
1)要求:主从机双向传送 256
个字节,主机方式2,中断;从机方式0,查询;设两机源和目标首址分别为 SRC、DST
2)分析:使用8259A的 I R 2 IR_2 IR2 ;中断服务程序中要判断 IBF
,即 IBF=1
输入 ,0
:输出。
3)硬件设计(中断方式的双向并行接口设计)
4)软件设计(主机)
主机:PA口方式2,双向,方式字=0C0H
从机:PA方式0,输入,PB方式0,输出,PC上输入,PC下输出,方式字=98H
开中断的方法:
INTE=1
IMRi=0
IF=1