定时器是通过固定频率的脉冲和计数实现定时功能的电路。计数器是用脉冲数量计数的电路。
在计算机和外设交互需要时间,执行指令也要特定的时间,比如让一个指示灯每三秒闪烁一次,说明CPU在打开这个外设三秒后再开关一次这个指示灯。因此就需要定时。
定时分为软件定时和硬件定时。软件定时就是写一段空循环,不断让CPU执行空循环直到时间所需时间为止。这种方法极大的浪费了CPU的算力,只可以用于定时时间短的简单系统。多数情况下用硬件定时,这就用到了8253A可编程计数器。这样做的好处一方面解放了CPU的算力,另一方面也将计数的任务下放到了计数器上,计数不再依赖于主频,又可以通过改命令字的方式提高了计数通用性。
8253是一种减法计数器,它内部有三个端口作为计数通道,每个端口的计数方式都是减法计数,即每接收到一个有效电平就将端口中的值减一直到为0,跳出计数。
8253的每个端口都是16位寄存器,因此最大可设置的计数值为0FFFFH = 65536。若用最大计数值,在设置时初值设置为0(因为8253的运行逻辑是先自减再判断,写成cpp程序如下)
while(-- cnt != 0) { // do something }
8253有不同的工作方式,总共六种,由程序员在编程时设置。
8253支持二进制编码计数和BCD码计数。也就是支持2进制计数和十进制计数。
8253的引脚结构
如图,共有4部分。分别为和CPU进行信息交换的数据总线,读写控制和片选部分,选择端口的片内选择部分以及三个端口的门控开关,输入输出(输入时CLK)。
8253内部结构
8253共有四个内部电路,前三个是三个计数通道,最后一个是控制电路。CPU的数据通过一根内部总线传输给目标寄存器。这三个计数通道公用一个命令端口。
计数器电路由一个16位初值寄存器,16位减一寄存器和一个16位数据锁存器和逻辑电路组成。
先说三个寄存器/锁存器
根据三者的功能,可以知道
再说逻辑电路
逻辑电路都连在减一寄存器上。分为输入端和输出端。
从8253的内部结构可以知道,我们一共要设置两个数据——计数初值和控制字。
初值的设置直接用OUT指令写入对应的初值寄存器之中就行。重点在如何设置正确的计数初值。
计数的速度依赖于时钟周期,不妨设其为$T_{CLK}$,假设我们需要延时$t$。那么就有。
$$
n = t / T_{CLK}
$$
如果需求是某频率 $f$,也有
$$
n = f / f_{CLK}
$$
由上我们已经知道8253的共有6种工作模式,并且有三个计数通道。同时它又支持二进制和十进制两种计数方式。因此不难知道控制字应该有包括读写控制在内的四部分。
注意
如果采用BCD码计数时,设置初值必须选用16进制。比如设置BCD模式下的计数初值为1234
MOV DX,PORT MOV AX,1234H; 注意不能写成1234 OUT DX,AX
因为我们在设置时不是设置的十进制数而是每个数位的BCD码,这刚好和二进制编码一一对应。
锁存命令的使用
当我们想知道当前计数值为多少时就需要先发出所存命令将端口中的值锁存在数据锁存器中,之后再用IN从对应的计数通道读取。比如读取通道2的当前计数值
MOV DX,PORT + 3 MOV AX,COMMAND; 1000XXXX OUT DX,AX IN AX,PORT + 2
略,看PPT
并行接口可一次传输多位数据,速度快,但不适合长距离传输,线材花销较大,在入微机系统等短距离系统中应用较多。
8255A有三种工作方式。
8255A共有三个端口,分别为A口,B口,C口。每个口的工作方式不同
A口: 工作方式0,1,2,即适用所有的工作方式
B口:工作方式0,1,适用前两种工作方式
C口:工作方式0,仅适用第一种工作方式
8255A支持三种数据传送方式。
注意
C口比较特殊,C口既可以当成一个八位的数据端口,也可以当成两个四位的数据端口,同时它们也可以和A口,B口连携使用。
C口既可以并行传递数据,也可以按位传送数据,有自己专门的控制字。
8255A的引脚结构
主要包括三口引脚,控制端(读写控制逻辑,片内选择,复位信号),数据总线,电源和接地端。
注意
复位端有效后,会将寄存器中所有位归零,之后再将所有端口置于输入状态。
8255A的内部电路逻辑结构
8255A的内部结构和8253差不多,都存在内部总线,读写逻辑控制电路,和输入端和输出端,但根据8255的特色功能有一些多出的部分。
因为C口可以和A,B口连携使用,所以还可以把端口分为A,B两组,因此还有对这两组的一个控制电路。C口的按位读数据也是由这两个控制电路实现。
同时并行接口传送数据时不是直接将数据写到寄存器中,而是添加一个缓冲中转——数据总线缓冲器。
最终如图。
A组控制管理A口和C口的高四位,B组控制管理B口和C口的低四位。
8255A控制字最高位是符号位,表示设置的是否是C的专用控制字。
根据编程要求,我们需要选择工作方式,选择端口,以及是否是C专用控制字。
因此有,
方式0用无条件或程序查询方式传送数据,方式1用中断请求查询方式。
其他摆了。