360 likes | 522 Views
第 8 章 计数器 / 定时器. 计数 器 与定时 器概述 可编程计数器 / 定时器 8253 定时器 / 计数器 8253 内部结构 8253 的 引脚功能 8253 的控制字 8253 的工作方式 8253 编程举例 8253 应用举例. 8.1 计数 器 与定时 器概述. 1. 计数功能 对事件的个数进行计数。 正计数:关心记录事件的次数。 倒计数:关心预先设定事件次数发生完的时刻。 可由硬件计数器实现,事件作为计数器的时钟,此时事件的出现频率不一定一成不变。. 2. 定时功能. 取得给定的时间间隔。
E N D
第8章 计数器/定时器 • 计数器与定时器概述 • 可编程计数器/定时器8253 • 定时器/计数器8253内部结构 • 8253的引脚功能 • 8253的控制字 • 8253的工作方式 • 8253编程举例 • 8253应用举例
8.1 计数器与定时器概述 • 1. 计数功能 • 对事件的个数进行计数。 • 正计数:关心记录事件的次数。 • 倒计数:关心预先设定事件次数发生完的时刻。 • 可由硬件计数器实现,事件作为计数器的时钟,此时事件的出现频率不一定一成不变。
2.定时功能 • 取得给定的时间间隔。 • 延时:某事件发生后间隔一定时间的时刻。 • 时标:给定时间间隔的连续脉冲。 • 可由硬件计数器来实现,一定频率的信号作为计数器的时钟,如果只计数到就终止,即为延时。如果连续不断的计数即可输出时标。
3. 计数器/定时器的用途 • 计数功能 • 作为计数个数到中断信号。 • 记录外部特定事件发生的个数。 • 定时功能 • 作为周期性定时中断信号。 • 用于分时性操作系统。 • 用作系统时钟基准。 • 作为一个可编程波特率发生器。用于异步串行通讯。 • 作为I/O设备输出定时信号。实现外设与CPU的同步。 • 节约CPU的时间延时。 • 作为音源。
8.2 可编程计数器/定时器8253 • 8.2.1 可编程计数器/定时器工作原理 • 1、计数功能 • 设置计数初值,按减1或加1计数,减到0或加到溢出时输出一个信号,标志预置的计数值到。此时输入的计数脉冲的间隔不一定是固定的。 • 计数功能关心的是计数脉冲的个数,而非脉冲的时间间隔。 • 2、定时功能 • 设定时常数(计数初值),对输入的周期性脉冲进行减1或加1计数,计数为0时输出定时到脉冲,若连续计数便可按定时常数输出时钟周期整数倍的定时间隔信号。 • 定时功能关心的是计数初值的写入时间与脉冲输出的时间间隔,要求输入的脉冲具有固定的频率。
8.2.2定时器/计数器8253内部结构 • Intel 8253是具有三个通道的16位定时器/计数器,可由软件设定6种工作方式。 • 8253内部有三个独立的计数器通道:计数器0、1、2,结构完全相同。 • 每个通道有6种工作方式,由控制寄存器选择。 • 控制寄存器为8位,计数初值计数器CR—16位,计数执行部件CE—16位,计数输出锁存器OL—16位。 • 计数执行部件为16位的减法计数器,但16位寄存器都可用于8位,便于与8位数据总线相连。 • 每个通道可对外部输入CLK进行二进制或十进制减1计数。计数由引脚GATE控制。 • 计数器归0时由OUT引脚输出信号。
CLK0 数据 D7~D0 计数器0 GATE0 缓冲器 OUT0 RD 读写 WR CLK1 控制 计数器1 A0 GATE1 A1 逻辑 OUT1 CS CLK2 控制 计数器2 GATE2 寄存器 OUT2 8253内部结构 8253的内部结构
D7~D0 CLK0 GATE0 OUT0 8位控制寄存器 计数初值 寄存器 高8位 低8位 计数器0 (CR) RD WR CS 计数执行 部件(CE) 高8位 低8位 高8位 低8位 计数输出锁存器 (OL) A1 A0 计数器1 计数器2 8253内部每个计数器通道的结构图
8.2.38253的引脚功能 • 8253具有24个引脚,各引脚功能如下: • D7~D0数据总线,双向三态,可直接与计算机系统数据总线相连。 • RD读信号,输入,低电平有效,若有效则CPU从8253内部读取数据. • WR写信号,输入,低电平有效,若有效则CPU将数据写入8253内部寄存器。 • CS片选信号,输入,低电平有效,与计算机连接时分配有效地址。 • A1A0内部计数器选择信号。 8253内部有三个计数通道,使用4个端口地址。
A0 CS A1 RD WR 功 能 0 1 0 0 0 对计数器0设置计数初值 0 1 0 0 1 对计数器1设置计数初值 0 1 0 1 0 对计数器2设置计数初值 0 1 0 1 1 设置控制字 0 0 1 0 0 从计数器0读出计数值 0 0 1 0 1 从计数器1读出计数值 0 0 1 1 0 从计数器2读出计数值 8253引脚功能 CLK0、CLK1、CLK2通道0、通道1和通道2的计数时钟输入端,下降沿使通道减1。 GATE0、GATE1、GATE2门控制,输入,高电平有效或上升沿有效,有效时才允许计数器对输入时钟进行计数。 OUT0、OUT1、OUT2通道输出信号,当计数器计数到“0”时由此引脚输出一信号。
D7 D0 SC1 SC0 RW1 M2 M1 M0 BCD RW0 8.2.4 8253的控制字及工作方式 1. 8253控制字 控制字必须写入控制口,说明如下: • SC1 SC0 计数器通道选择 0 0 通道0 0 1 通道1 1 0 通道2 1 1 非法
8253控制字 • RW1 RW0 计数器读写选择 0 0 计数器锁存 0 1 只读写低8位 1 0 只读写高8位 1 1 先低8位,再高8位 • M2M1M0计数器工作方式选择 0 0 0 方式0 0 0 1 方式1 x 1 0 方式2 x 1 1 方式3 1 0 0 方式4 1 0 1 方式5 ④ BCD 计数器计数模式选择 0 二进制计数器 1 BCD码计数器
2. 8253 编程命令 • 因各计数器有自己的端口地址,所以没有太多顺序要求,但必须遵守两条规定: • 设置计数初值前必须先写控制字 • 设置计数初值时要与控制字中的D5 D4位规定的读写指示一致。 • 命令字共4个: • 写控制字命令 • 设置计数初值(时间常数)命令 • 读出命令,读出当前计数值 • 锁存命令,配合读出命令,先锁住,再读出。
N=4 CW WR CLK OUT FF 0 1 3 2 4 方式0时序图 3. 8253工作方式 • 模式0 — 计数结束产生中断 • 控制字写入后OUT即变为低电平,当计数器为0时,输出OUT变为高电平,并停止现行操作。 • 计数初值写入后在下一个CLK下降沿才送入计数器,因此OUT要在CPU写入计数初值后经N+1个CLK之后才变高。 • 当GATE变为低电平时计数停止,再变为高电平时计数继续进行。 • 若计数过程中重新送入初值,则按新值重新计数。
N=3 CW WR CLK GATE OUT 0 3 2 1 3 2 FF FE 方式1时序图 模式1 — 可重新触发单稳态触发器 • 写入控制字后OUT变为高电平,GATE上升沿后,下一个CLK的下降沿使得OUT为低电平并开始计数,回零时OUT变为高电平。 • GATE再来一次上升沿后会再次使OUT变为低电平,计数器以初值重新计数。 • 再次给通道写入时间常数,不影响现行操作过程,GATE再次触发后才按新的时间常数操作。
CW N=3 WR CLK GATE OUT 1 1 1 2 3 3 2 3 2 方式2时序图 模式2 — 分频器 • 写入控制字后OUT为高电平,输入时间常数后,下一时钟开始计数,减到1时输出变为低电平,经过一个CLK输出变为高电平,计数重新开始。 • GATE=1计数进行,GATE=0计数停止,且下一个CLK下降沿计数器重新赋初值,GATE变为高电平,计数重新开始。 • 计数期间送入新值,GATE若维持高电平,本周期继续进行,下一个周期按新值计数操作。 • 在计数计到1之前,若写入新值,而GATE又出现上升沿,则在下一个CLK下降沿,以新值重新计数。
CW N=4 WR CLK GATE OUT 4 3 2 1 3 2 4 1 方式3时序图 模式3 — 方波发生器 • 写入控制字后OUT为高电平, 输入时间常数后,下一时钟开始计数,计到一半时输出变为低电平,计到终值时变为高电平,并开始下一次计数过程。 • 若N为偶数,高低电平持续时间相等;若为奇数,则高电平持续时间为(N+1)/2,低电平持续时间为(N-1)/2。 • GATE=1计数进行,GATE=0计数停止,OUT立即为高,计数器重新赋初值,GATE变高,在下一个CLK下降沿计数重新开始。 • 计数期间送入新值,本周期继续进行,下一个周期按新值计数。
CW N=3 WR CLK GATE OUT FC FF FE FD 2 1 0 3 方式4时序图 模式4 — 软件触发选通信号发生器 • 计数器主要是靠写入初始值这个软件操作来触发计数器工作的,每次通过写入新的初始值使计数器重新开始工作。 • OUT平时为高电平,计数到0时,输出OUT 变低,一个时钟周期后又变高。即只有在计数到0时,才输出负脉冲作为选通信号。 • GATE=1允许计数,GATE=0禁止计数,GATE不影响OUT电平输出。 • 计数期间送入新的时间常数,则下一个时钟按新值重新计数。
CW N=3 WR CLK GATE OUT 2 1 3 FF 0 FE 1 0 3 2 方式5时序图 模式5——硬件触发选通信号发生器 • 写入控制字后OUT变为高电平,输入时间常数后由GATE上升沿启动计数。计数为0时输出一个时钟的负脉冲,并停止现行操作。 • 计数过程中,若GATE又来一个上升沿,则下一个时钟计数器重新赋值计数。 • 计数过程中写入时间常数,当前周期不受影响,只有下一个 GATE上升沿才启动新值计数。
8.2.5 8253编程举例 • 使用8253时,必须首先进行初始化编程,其步骤为: • 先向控制口写入控制字; • 再向每个通道端口地址写入计数初值:若规定只写低8位,则高8位自动置0;若规定只写高8位,则低8位自动置0;若规定写16位,则先写低8位,再写高8位。 • 最大计数初值0: • 二进制: 216 =65536 • BCD码: 104 =10000
例1: 8253计数器工作于模式3,计数器初值15,时钟脉冲频率为2MHz,确定OUT端输出方波的特性。 解:TCLK=1/2 s =500ns 计数器初值15为奇数,输出分频波高电平宽度: TCLK(N+1)/2=4s 输出分频波低电平宽度: TCLK(N-1)/2=3.5s
例2:设8253的口地址为40H ~ 43H,如要求8253的通道1工作于方式3,按BCD码计数,计数值为十进制6000;通道2工作于方式2,按二进制计数,计数初值为390,试编程初始化8253。 MOV AL,67H ;控制字01,10,011,1 通道1,只装高8位,方式1,BCD码 OUT 43H,AL ;送通道1控制字 MOV AL,60H ;计数初值为6000,只装高8位,低8位自动赋0 OUT 41H,AL MOV AL,0B4H;10,11,010,0 通道2,16位,方式2,二进制 OUT 43H,AL;送通道2控制字 MOV AX, 390; OUT 42H,AL;先写计数初值低8位 MOV AL,AH; OUT 42H,AL;后写计数初值高8位
8253的读操作方法及编程举例 • 为了对计数器的计数值进行显示或实时处理,常需要读取计数通道的当前计数值,它是由CPU访问每个通道的计数值锁存器OL实现的。读当前计数值的端口地址和写入计数初值的端口地址是相同的。读操作必须严格按控制字D5 D4位确定的格式进行:如果是8位计数,则 只 需 读一次;若是16位计数,则同一端口地址要读两次,第一次读入低8位计数值,第二次读入高8位计数值。 • 8253有以下两种读当前计数值的方法
①读之前先停止计数:可以在读之前用GATE信号控制计数器暂停计数,或由外部逻辑禁止所要读入的计数通道的CLK脉冲输入。如果不先停止计数,那么,分先后两次读入的高低字节的值可能不属于同一个16位计数值,所以最好先从外部禁止计数,然后执行类似如下程序读入(设8253的端口地址为E0H ~ E3H): IN AL,0E0H;读入通道0的低8位 MOV BL,AL IN AL,0E0H ;读入通道0的高8位 MOV BH,AL ;读入的16位计数值存入BX中。
②读之前先送计数值锁存命令:计数值锁存命令是控制字的一种特殊形式,需写入控制寄存器的端口地址。锁存命令的D7 D6位的编码决定所要锁存的计数通道,锁存命令的D5 D4必须为“00”(锁存命令标志)。锁存命令的低4位可以是全“0”。因此,三个计数器的锁存命令分别为:通道0是00H,通道1是40H,通道2是80H。 例如,要读取通道2的计数值,程序如下: MOV AL,80H; 10 00 0000B向通道2发锁存命令 OUT 0E3H,AL;锁存命令写入控制寄存器(锁住通道2的计数值)IN AL,0E2H;读通道2的OL的低8位 MOV BL,AL IN AL,0E2H;读通道2的OL的高8位 MOV BH,AL
8253 +5V GATE0 D7 D7 GATE1 ~ ~ D0 PB0(8255) D0 GATE2 IRQ0(8259) OUT0 RD IOR 刷新电路 OUT1 IOW WR OUT2 A1 A1 驱动器 A0 A0 CLK0 PB1(8255) CLK1 CLK2 CS +5V 74LS175 PCLK C Q A15 74LS138 +5V D Q A14 74LS30 A13 G1 A12 G2A Y2 A11 A8 G2B A10 A7 C A9 A6 B A5 74LS04 A 8.2.6 IBM PC/XT中的8253应用举例 8253的接口电路
端口 地址 A4 A3 A2A1 A0 A15~A8 A7 A6 A5 通道0 0 0 040H 通道1 0 1 041H 0~ 0 0 1 0 X X X 1 0 通道2 042H 1 1 控制口 043H 8253与8088计算机连接说明 • 8253数据线D7~D0接系统数据总线的低8位。 • 8253的A1和A0分别接系统的A1和A0 • 由74LS138,74LS30和74LS04译码选中8253 • 8253三个通道的时钟由PCLK经D触发器二分频得到,频率为:2.38636/2=1.1931816MHz
通道0定时OUT0接8259A的IR0,通道1刷新动态存储器,通道2控制扬声器发声。通道0定时OUT0接8259A的IR0,通道1刷新动态存储器,通道2控制扬声器发声。 通道0:为系统电子钟提供基准时间和软驱马达定时。计数器0为模式3(方波发生器)GATE0固定高电平,OUT0作为中断请求接8259A中断控制器的IRQ0,OUT0输出时钟频率为1.19MHz/216 =18.2Hz,即每秒产生18.2次输出信号,输出一个定时脉冲,产生一个中断请求(周期约55ms),计时软件据此计时。控制字为36H。 通道1:作为DRAM刷新的定时信号。工作于模式2,计数值为12H=18(1.19MHZ/18分频 ),每隔15.12μS产生一次刷新请求,此信号送到DMA 8237A-5的通道0,作为DMA请求信号。由8237A-5执行DMA操作完成DRAM一行的刷新。 通道2:输出信号接扬声器,工作于模式3(方波发生器),初值为533H,方波频率为1.19MHz/1331=894Hz
BIOS对8253的初始化程序 通道0: MOV AL,36H ;控制字:00110110—通道0,16位,方式3,二进制 OUT 43H,AL ;写入控制寄存器 MOV AL, 0;初值为0000H,计数65536次(最大) OUT 40H,AL;写入CR0的低8位计数值 OUT 40H,AL;写入CR0的高8位计数值 • 计数器0工作于方波发生器方式,对CLK(1.1931816MHz)进行65536分频。时钟周期Tc=1/1.19×103 ≈840ns • 计数器0的输出端OUT0接8259的IR0,每次归0产生一次中断请求,中断类型码由BIOS设置为8。 • OUT0端输出周期为T0=840ns×65536≈55ms,即每隔55ms定时时间发出一次中断请求。通道0的时间间隔是计算机系统时钟基础。 • OUT0端输出方波频率f0=1/T0 ≈ 18.2 ,即每秒钟来18.2次中断。
通道1: MOV AL,54H ;控制字01010100 通道1,低8位,方式2,二进制 OUT 43H,AL ;写入控制寄存器 MOV AL,12H ;初值为18 OUT 41H,AL ;写入计数值低8位,高8位自动为0, • 通道1给DMA控制器提供时钟,用于定时(约15μs)向DMA请求DRAM刷新,计数初值为12H。 • OUT1输出周期为:T1=840ns×18≈15.12μs,于是,2ms内可有132次刷新,大于IBM-PC/XT要求的DRAM刷新在2ms内应有128次的规定。 • OUT1输出频率为f1=1/T1=66.1KHz的连续负脉冲。
通道2: MOV AL,0B6H;控制字10110110 通道2,16位,方式3,二进制计数 OUT 43H,AL ;写入控制寄存器 MOV AX,533H ;初值为533H OUT 42H,AL ;写入计数值低8位 MOV AL,AH ; OUT 42H,AL ;写入计数值高8位。 IN AL,62H ;读入8255的B口数据 MOV AH,AL ;保护B口原值 OR AL,03H ;置1 PB1和PB0 OUT 62H,AL ;输出 • 通道2:控制字为B6H,计数初值为533H=1331 。 • OUT2输出方波周期T2=840ns×1331≈1.12ms,频率f2=1/T2=894Hz,894Hz的方波送至扬声器,驱动扬声器发声。 • 扬声器发声还受8255的PB0和PB1控制。
8253应用举例 例:由8253的计数器0定时55ms 控制扬声器变调发声,响5.5秒后停止。 • 说明 • 8253计数器0的OUT0接8259A的IR0,由BIOS初始化,中断类型码为08H,并在完全嵌套方式下工作。 • 8253计数器0由BIOS设置为模式3,定时时间为55ms。 • 扬声器由8253的计数器2控制发声频率,发声允许由8255的PB0和PB1控制。
DOS功能调用25H号子功能为设置中断向量。 • 入口参数 AH=25H,AL=中断类型码 DS:DX 中断服务程序入口地址 • 返回参数:无 • DOS功能调用35H号子功能为取中断向量 • 入口参数 AH=35H,AL=中断类型码 • 返回参数 ES:BX 中断服务程序入口地址 • 中断服务程序为INT_08H • 保护现场和恢复现场; • 中断返回前要开中断并发EOI; • 中断返回IRET。 • 每次定时器0中断使扬声器的发声频率的分频常数增加100,并使计数变量count增1。 • 主程序查询count到100后停止扬声器发声,恢复中断向量,程序退出。
8253应用程序 • Int_08h proc far ;中断服务子程序 • push ax • push ds • mov ax, data • mov ds, ax • mov al, 0b6h • out 43h, al • mov ax, constant • add ax, 100 • mov constant, ax • out 42h, al • mov al, ah • out 42h, al • inc count • mov al, 20h ;发EOI • out 20h, al data segment old_int08h dd ? count dw 0 constant dw 60 state db ? data ends st_seg segment stack db 256 dup (?) st_seg ends code segment assume cs:code,ds:data
mov dx, offset int_08h mov al, 08h int 21h mov ax, data mov ds, ax ;打开8255控制 in al, 61h mov state, al or al, 3 out 61h, al sti ;开中断 pop ds pop ax sti iret Int_08h endp ;主程序 main proc far mov ax, data mov ds, ax cli ;关中断 mov ah, 35h ;取中断向量 mov al, 08h int 21h mov word ptr old_int08h, bx mov word ptr old_int08h[2], es push cs ;设置新中断向量 pop ds mov ah, 25h
;判断5.5S是否到 main1: mov ax, count cmp ax, 100 jc main1 mov al, state ;恢复8255状态 out 61h, al mov ah, 25h ;恢复原中断向量 lds dx, old_int08h mov al, 08h int 21h mov ax, 4c00h ;返回操作系统 int 21h main endp code ends end main