8253控制字
概述
图7-45
中左下角的是控制字寄存器,其操作端口是0x43,它是8位大小的寄存器
控制字寄存器也称为模式控制器,在控制字寄存器中保存的内容称为控制字,控制字用来设置所指定的计数器(通道)的工作方式、读写格式及数制,为方便叙述,把计数器的"工作方式、读写格式及数制"赞称为控制模式
三个计数器是独立工作的,每个计数器都必须明确自己的控制模式才知道该怎样去工作(计数),它们各自的控制模式都要以控制字的形式在同一控制字寄存器中设定。所以,控制字中有相关的字段来选定操作那个计数器
控制字结构
控制字由8位二进制组成
SC1和SC0位
SC1和SC0位是选择计数器位,即Select Counter,或者叫选择通道位,即Select Channel
- 在8253内部有3个独立的计数器,每个计数器都有自己的控制模式,但这三个计数器的控制字是共用同一个控制字寄存器写入的
- 所以,此处用SC1和SC0这两位去选择待操作的计数器,也就是此控制字用来设置那个计数器
- 这两位可组合4个寄存器名称,二进制00b ~ 10b 分别对应计数器0 ~ 计数器2
RW1和RW0位
RW1和RW0位是 读/写/锁存操作位,即Read/Write/Latch,用来设置待操作计数器(通道)的读写及锁存方式
- 计数器是16位宽度,当我们往计数器中写入计数初值时,或者读取计数器中的数值时,可以指定读写低8位,还是高8位
- RW1和RW0这两位组合成4种读写方式
M2~M0
M2M0这三位是工作方式(模式)选择位,即Method或Mode。每个计数器有6种不同的工作方式,即方式0方式5
BCD
8253的各个计数器都有两种计数方式: 二进制方式和十进制方式,其中十进制方式就是用BCD码来表示
BCD,即Binary-Coded Decimal,称为“二进制码的十进制数”。十进制最大数为9,也就是需要用4位二进制来表示1位十进制
BCD位是数制位,用来指示计数器的计数方式是BCD码,还是二进制数
当BCD位为1时,则表示用BCD码来计数,如0x1234,则表示十进制数1234。BCD码的初始值范围是0 ~ 0x9999,也就是说BCD码所表示的十进制范围是0~9999。0值则表示十进制10000
当BCD位为0时,则表示用二进制来计数,如0x1234,则表示十进制4660。二进制数的初始值范围是00xFFFF,即十进制范围是065535,0值表示65535
8253工作方式
图例
计数器开始计数需要两个条件
(1) GATE为高电平,即GATE为1,这是由硬件控制的
(2) 计数初值已经写入计数器中的减法计数器,这是由软件out指令控制的
当这两个条件具备后,计数器将在下一个时钟信号CLK的下降沿开始计数
在数字电路中,电压的高低用逻辑电平来表示。把高于3.5V的电压规定为高电平,用数字1表示
低于0.3V的电压规定为低电平,用数字0表示。把电平数字由0变成1的一瞬间称为上升沿,把电平数字由1变成0的一瞬间称为下降沿
计数器的启动
软件启动
软件启动是指上面硬件负责的条件1已经完成,也就是GATE已经为1,目前只差软件来完成条件2,即尚未写入计数初值
只要软件负责的条件准备好,计数器就开始启动
当处理器用out指令往计数器写入计数初值,减法器将此初值加载后,计数器便开始计数
工作方式0、2、3、4都是软件启动计数过程
硬件启动
硬件启动是指上面软件负责的条件2已经完成,即计数初值已写入计数器。目前只差硬件来完成条件1了,也就是门控信号GATE目前还是低电平,即目前GATE=0,只要硬件负责的条件准备好,计数器就开始启动
GATE引脚是由外部信号来控制的,只有当GATE由0变1的上升沿出现时,计数器才开始启动计数
工作方式1、5都是硬件启动计数过程
计数器终止
强制终止
有些工作方式中,计数器是重复计数的,当计时到期(计数值为0)后,减法计数器又会重新把计数初值寄存器中的值重新载入,继续下一轮计数器,比如工作方式2和工作方式3都是采用此方式计数,此方式常见于需要周期行发信号的场合
对于采用此类循环计数工作方式的计数器,只能通过外加控制信号来将其计数过程终止,办法是破坏启动计数的条件:将GATE置为0即可
自动终止
有些工作方式中,计数器是单次计数,只要定时(计数)一到期就停止,不再进行下一轮计数,所以,计数过程自然就自动终止了
比如工作方式0、1、4、5都是单次计数,完成后自动终止
如果想在计数过程中将其终止怎么做呢?还是用那个简单粗暴可依赖的方法,将GATE置0
计数器的6种工作方式
方式0: 计数结束中断方式(Interrupt on Terminal Count)
方式0也称为“计数结束输出正跳变信号”方式,其典型应用是作为事件计数器
在方式0时,对8253任意计数器通道写入控制字,都会使该计数器通道的OUT变为低电平,直到计数值为0
当GATE为高电平(条件1),并且计数初值已经被写入计数器(条件2)后,注意,此时计数器并未开始计数,计数器有自己的工作节奏,就是时钟信号CLK
计数工作会在下一个时钟信号的下降沿开始。
方式0下的计数工作由软件启动,故当处理器用out指令将计数初值写入计数器,然后到计数器开始减1,这之间有一个时钟脉冲的延迟
之后,CLK引脚每次收到一个脉冲信号,减法计数器就会将计数值减1
当计数值递减为0时,OUT引脚由低电平变为高电平,这是个由低到高的正跳变信号,此信号可以接在中断代理新芯片8259Q的中断引脚IR0上,所以此信号可以用来向处理器发出中断,故称为计数器结束“中断”方式
方式0进行计数时,计数器只是单次计数,计数为0时,并不会再将计数初值寄存器中的值重新载入。此方中,门控信号GATE用于允许或禁止计数,当GATE=1时允许计数,GATE=0时则禁止计数
方式1:硬件可重触发单稳(Hardware Retriggerable One-Shot)
方式1的典型应用是作为可编程单稳态触发器,其触发信号是 GATE,这是由硬件来控制的,故此方式称为硬件可重触发单稳方式。
在方式 1 下,由处理器将计数初值写入计数器后, OUT引脚变为高电平
不过, 无论此时 GATE 是高电平,还是低电平,计数器都不会启动计数,而是等待外部门控脉冲信号 GATE 由低到高的上升沿出现,这是由硬件启动的,之后才会在下一个时钟信号 CLK 的下降沿开始启动计数,同时会将 OUT引脚变为低电平
此后,每当 CLK 引脚收到一个时钟脉冲信号时,在其下降沿,减法计数器便开始对计数值减 l
OUT 引脚的低电平状态一直保持到计数为0,当计数为0时,OUT引脚产生有低到高的正跳变信号
方式2: 比率发生器(Rate Generator)
方式 2 是比率发生器方式,即按照比率来分频,其典型应用就是分频器,故也称为分频器方式。在我们的应用中,也将选用此方式作为计数器的工作方式,以改变时钟中断的频率。
分频器的作用是把输入频率变成符合要求的输出频率,其作用就像个变速箱,本来在一端接入的转速很快,经过里面各种齿轮相互配合,另一端输出的转速很慢。
举个生活中的例子来解释分频器原理,比如往货车上装货物,工人A 负责把货物从仓库中搬出来放到货车前,工人 C 负责把货物装上车,工人B 负责统计搬上车的货物总数,为了方便统计,每当工人A 从仓库送来 2 件货物,他才通知工人 B 来往车上搬
假如工人A一次从仓库搬 1 件货物,一分钟搬 10 次,工人 B 对搬来的货物计数,只要一满 2 件他就匾知工人 C 搬货,也就是说工人 C 每次搬 2件,一分钟搬 5 次
此过程中,工人A 相当于输入脉冲信号 CLK,其频率是 10 次/分钟,工人 B 相当于分频器,它将工人 C 的搬货频率降低。工人 C 相当于输出信号 OUT,其频率是 5 次/分钟。这就是分频的道理。
当处理器把控制宇写入到计数器后, OUT 端变为高电平。在 GATE 为高电平的前提下,处理器将计数初值写入后,在下一个 CLK 时钟脉冲的下降沿,计数器开始启动计数,这属于软件启动
当计数值为1 时, OUT 端由高电平变为低电平,此低电平的状态一直到计数为 0 ,也就是持续一个 CLK 周期。当计数值为1 时, OUT 端由高电平变为低电平,此低电平的状态一直到计数为 0 ,也就是持续一个 CLK 周期
此方式的特点是计数器计数到达后,自动重新载入计数初值,不需要重新写入控制字或计数初值便能连续工作
当计数初值为 N 时,每 N 个 CLK 时钟脉冲,就会在 OUT端产生一个输出信号,这样一来,输入信号CLK 和输出信号 OUT的关系是 N: 1 ,故其作用就是个分频器
综上所述,方式 2 主要用在循环分频的场合
方式3: 方波发生器(Square Wave Generator)
计数器在方式 3 下工作,就相当于一个方波发生器
当处理器把控制字写入到计数器后,端输出高电平。在 GATE 为高电平的前提下,在处理器把计数初值写入计数器后的下一个 CLK 时钟脉冲的下降沿,计数器开始计数。
如果计数初值为偶数,在每一个 CLK 时钟脉冲发生时,计数值均减 2,当计数值为 0 时, OUT 端由高电平变为低电平,井且自动重新载入计数初值,开始下一轮计数。在新的一轮计数中,当计数值再次为0 时, OUT 端又会变成高电平,同时再次载入计数初值,又开始一轮新的计数。
如果计数初值为奇数,并且 OUT 端为高电平,则在第一个时钟脉冲的下降沿将计数减 1 ,这样剩下的计数值便为偶数了,所以在之后的每个时钟脉冲,计数值都被减 2
当计数值变为 0 时, OUT 端又变成低电平,同时自动从计数初值寄存器中载入计数初值开始下一轮计数。注意,在新一轮计数中,第一个时钟脉冲会将计数值减 3,这样剩下的计数值也为偶数,之后的每个时钟脉冲都会将计数值减 2
当计数值又减为 0时, OUτ 端又重新回到高电平,同时自动从计数初值寄存器中载入计数初值,开始又一轮循环计数。
方式 3 和方式 2 类似,都是软件启动,并且 0盯端都是周期性脉冲,用在循环计数的场合。
方式4: 软件触发选通(Software Triggered Strobe)
当处理器把控制字写入到计数器后, OUT 端变成高电平。在 GATE 为高电平的前提下,在处理器把计数初值写入计数器后的下一个 CLK 时钟脉冲的下降沿,计数器开始计数,所以是软件启动。
当计数值为 1 时, OUT 端由高电平变为低电平,当计数值为 0,即持续一个 CLK 时钟周期后, OUT端又回到高电平,此时计数器停止计数
此方式和方式。类似,都是单次计数,只有在重新写入控制字或重新写入计数初值时才会重新开启计数。
方式5: 硬件触发选通(Hardware Triggered Strobe)
此方式与方式 4 类似,都是一次计数,区别是计数启动的方式不同,方式 5 是硬件启动。
方式 5 中,当处理器把控制字写入到计数器后, OUT端变成高电平。处理器把计数初值写入计数器后,计数工作要等到外部门控脉冲信号 G且E 由低到高的上升沿出现时才开启,这是由硬件启动的。
当计数值为1时,OUT端由高电平变为低电平,保持一个CLK周期,即计数值变为0时,OUT端又变成高电平,同时停止计数
8253工作模式总结
计数器0多久发一个中断信号?
8253 的目的就是为了提升时钟中断信号的频率,而时钟中断信号是由计数器 0 负责产生的
其实这是利用了分频器的原理,将高频的输入脉冲信号 CLK 转换为低频的输出信号 OUT,此信号就是时钟中断信号
这与计数器的工作方式有关,您已经知道了,并不是所有的工作方式都能让计数器周期性地发出中断信号,假设计数器。工作在方式 2 下,下面介绍下中断信号产生的原理
CLK 引脚上的时钟脉冲信号是计数器的工作频率节拍,三个计数器的工作频率均是 1.19318MHZ,即一秒内会有 1193180 次脉冲信号
每发生一次时钟脉冲信号,计数器就会将计数值减 1 ,也就是 1 秒内会将计数值减 1193180 次 1
当计数值递减为 0 时,计数器就会通过 OUT 引脚发出一个输出信号,此输出信号用于向处理器发出时钟中断信号
一秒内会发出多少个输出信号,取决于计数值变成 0 的速度,也就是取决于计数初始值是多少
默认情况下计数器。的初值寄存器值是 0,即表示 65536。计数值从 65536变成 0 需要修改 65536 次,所以,一秒内发输出信号的次数为 1193180/65536,约等于 18.206,即一秒内发的输出信号次数为 18.206 次,时钟中断信号的频率为 18.206Hz。
1000 毫秒/ ( 1193180/65536 )约等于54.925 ,这样相当于每隔 55 毫秒就发一次中断
8253初始化步骤
往控制字寄存器端口 Ox43 中写入控制字
用控制字为指定使用的计数器设置控制模式,控制模式包括该计数器工作时采用的工作方式,读写格式及数制
往控制字寄存器端口 Ox43 中写入控制字
计数初值要写入所使用的计数器所在的端口,即若使用计数器。,就要把计数初值往 Ox40 端口写入,若使用的是计数器 1 ,就要把计数初值往 Ox41 端口写入,依次类推
计数初值寄存器是 16 位,高 8 位和低 8 位可单独使用,所以初值是 8 位或 16 位皆可。若初值是 8 位,直接往计数器端口写入即可 。 若初值为 16 位,必须分两次来写入,先写低 8 位,再写高 8 位
8254 读回命令
8254 较8253 的改进主要有:8254 的计数频率更高;8254 多了一个读回命令。这个读回命令(写入控制寄存器)可以使3 个计数器的计数初值和状态锁存,向CPU 返回一个状态字
8254 中每个计数器都有一个状态字,可通过读回命令将其锁存,然后由CPU 读取。状态字的格式如下图所示
格式中D5~D0 位为写入此计数器的控制字的相应部分。D7 位反映该计数器的输出引脚的现行状态,输出为高电平,D7 = 1;输出为低电平,D7 = 0。
D6 位反映计数初值寄存器中计数初值是否已装入减1 计数器中,若最后写入计数初值寄存器的计数值已装入减1 计数器,则D6 = 0,表示可读计数;若计数初值寄存器的计数值未装入减1 计数器,则D6 = 1,表示无效计数,读取的计数值将不反映刚才写入的那个新计数值。
读出命令用来读取计数器的当前计数值,读取命令分两步完成:
- (1)发出锁存命令,使当前计数值锁存在输出锁存器(OL)中
- (2) 读输出锁存器(OL),获得当前计数值
- 必须注意:计数值是16位的,但8253均为8位端口,必须分两次读取,才能获得16位的值,为了避免第1次读
- 取后,计数值发生变化,必须使用锁存命令使计数值锁存在输出锁存器中,然后分两次从输出锁存器中读取16位值
- 例:读出计数器0的当前计数值,放在BX中
MOV AL,00000000B ;锁存,
OUT 73H,AL
IN AL,70H ;当前计数值低8位
MOV BL,AL
IN AL,70H ;当前计数值高8位
MOV BH,AL ;读取后,OL的值又随计数执行部件变化