汇编语言:使用8259中断实现定时/计数器实验

一、实验目的

  1. 掌握定时/计数器8254的基本工作原理和编程方法
  2. 利用TPC-ZK-II实验板上的 8254向中断源发出中断申请,其中断请求用IRQ3(系统总线区的IRQ)
  3. 了解七段数码管显示原理,掌握其显示接口技术,了解数字时钟原理,掌握实现数字时钟技术
  4. 掌握中断控制器8259A的应用编程

二、实验原理

  本实验的硬件中断只有可屏蔽中断,由 8259中断控制器管理。

1.8259内部结构

    8259A是专为控制优先级中断而设计的芯片。它将中断源按优先级排队、辨认中断源、提供中断向量的电路集成于一体,只要用软件对它进行编程,就可以管理8 级中断。

    它由中断请求寄存器(IRR)、优先级分析器、 中断服务寄存器(ISR)、中断屏蔽寄存器(IMR)、数据总线缓冲器、读写控制电路和级联缓冲器、比较器组成。

  中断请求寄存器:寄存所有要求服务的请求IR0~IR7。

  中断服务寄存器:寄存正在被服务的中断请求。         

  中断屏蔽寄存器:存放被屏蔽的中断请求,该寄存器的每一位表示一个中断号, 该位为1,屏蔽该号中断,否则开放该号中断。

    数据总线缓冲器:是双向三态的,用以连接系统总线和8259A内部总线, 通过它可以由CPU对8259A写入状态字和控制字。

    读写控制电路:用来接受I/O命令,对初始化命令和操作命令字寄存器进行写入,以确定8259A的工作方式和控制方式。

    级联缓冲器/比较器:用于多片8259A的连接,能构成多达64级的矢量中断系统。

2.中断源与类型

中断源

中断类型号

中断功能

IRQ0

08H

时钟

IRQ1

09H

键盘

IRQ2

0AH

保留

IRQ3

OBH

串行口2

IRQ4

0CH

串行口1

IRQ5

0DH

硬盘

IRQ6

0EH

软盘

IRQ7

0FH

并行打印机

表2-1 中断类型号

       8个中断源的中断请求信号线IRQ0~IRQ7在主机的62线ISA总线插座中可以引出,系统已设定中断请求信号为“边沿触发”,普通结束方式。对于微机内又扩展了一片8259中断控制,IRQ2用于两片8259之间级连,对外可以提供16个中断源,如表2-2所示。

中断源

中断类型号

中断功能

IRQ8

070H

实时时钟

IRQ9

071H

用户中断

IRQ10

072H

保留

IRQ11

O73H

保留

IRQ12

074H

保留

IRQ13

075H

协处理器

IRQ14

076H

硬盘

IRQ15

077H

保留

表2-2 扩展中断类型号

       TPC-ZK-II实验板上,固定的接到了3号中断IRQ3上,即进行中断实验时,所用中断类型号为0BH。

       中断控制器 8259可利用系统初始化设定,如不进行新的初始化,只需对  8259中断控制器的屏蔽寄存器设定 IRQ3为中断允许,其他原有中断允许保持不变。

3.8254设置

       将实验板上的 8254的通道,设定为10ms周期信号发生器,该芯片的通道1设定为计数器,其输入来自定时器通道 0的输出,利用通道 1的计数器输出作为IRQ3中断请求信号。

4.8254连接图

图2-3 8254定时器连线

    8254定时器的CLK0由实验板上的1MHZ振荡器来提供。8254定时器的CLK0由实验板上的1MHZ振荡器来提供。

5.数码管连接图与段码表

       数码管显示接口电路如图2-4所示。实验台上的七段数码管为共阴型,段码采用同相驱动,输入端加高电平,选中的数码管亮,位码加反相驱动器,位码输入端高电平选中。

图2-4数码管显示电路

       本实验需要 PB7-PB0/8255接dp-a /LED数码管,PC3-PC0/8255接  S3-S0/LED数码管。七段数码管的字型代码表如表2-5所示。

表2-5 七段数码管的字型代码表

三、实验框图与流程图

图3-1 实验程序设计流程图

四、实验程序清单

data  	segment
p8259   equ  21h        ;端口首地址 
p8255   equ  288h       ;端口首地址 
p8253   equ  280h       ;IO Y1 

led  db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh            
sec1 db 2 
sec2 db 5 
min1 db 8 
min2 db 5 
mes  db 42h 
Old_0A   DW 0,0        
Old_8259    DB  0 
data ends 

stacks segment     
    db 64 dup (0) 
stacks ends 

code segment  
    assume cs:code,ds:data,es:data
start:  
    mov ax,data  
    mov ds,ax 
    cli                             
    mov al,00110110b 
    mov dx,p8253+3                   
    out dx,al                     
    mov ax,10000                  
    mov dx,p8253 
    out dx,al 
    mov al,ah                        
    out dx,al 
    mov al,01110110b 
    mov dx,p8253+3                  
    out dx,al                     
    mov ax,100                     
    mov dx,p8253+1  
    out dx,al 
    mov al,ah                        
    out dx,al   
                             
    PUSH ES                        
    PUSH BX 
    MOV Al,0BH                         
    mov ah,35h   
    INT 21H                       
    MOV Old_0A+2,ES                      
    MOV Old_0A,BX         
    POP BX        
    POP ES  
    
    PUSH DS
    MOV AL,0BH                   
    MOV AH,25H                
    MOV DX,SEG INT_0A  
    MOV DS,DX                  
    MOV DX,OFFSET INT_0A 
    INT 21H  
    POP DS 

    MOV AL,10000000B           
    MOV DX,P8255+3 
    OUT DX,AL 
    
    IN AL,P8259                 
    MOV OLD_8259,AL           
    AND AL,11110111B           
    OUT P8259,AL 
    STI                           

PLAY: 
    LEA BX,LED                   
    MOV DL,SEC1                  
    MOV DH,0          
    MOV SI,DX 
    MOV AL,[BX][SI]        
    MOV DX,P8255+1               
    OUT DX,AL  
    MOV AH,00001110B          
    MOV AL,AH  
    MOV DX,P8255+2                
    OUT DX,AL  
    PUSH CX 
    MOV CX,9fffH                
DELAY1:
    nop
    nop 
    LOOP DELAY1       
    POP CX   
    MOV AH,00001111B      
    MOV AL,AH  
    MOV DX,P8255+2                
    OUT DX,AL  
    MOV DL,SEC2                    
    MOV DH,0  
    MOV SI,DX 
    MOV AL,[BX][SI]        
    MOV DX,P8255+1               
    OUT DX,AL 
    MOV AH,00001101B     
    MOV AL,AH 
    MOV DX,P8255+2                
    OUT DX,AL   
    PUSH CX 
    MOV CX,9fffH                 
DELAY2:
    nop
    nop 
    LOOP DELAY2       
POP CX 
    MOV AH,00001111B      
    MOV AL,AH  
    MOV DX,P8255+2                
    OUT DX,AL  
    MOV DL,MIN1                    
    MOV DH,0 
    MOV SI,DX 
    MOV AL,[BX][SI]        
    MOV DX,P8255+1                 
    OUT DX,AL 
    MOV AH,00001011B     
    MOV AL,AH 
    MOV DX,P8255+2                 
    OUT DX,AL  
    PUSH CX 
   MOV CX,9fffH                   
DELAY3:
    nop
    nop 
    LOOP DELAY3       
    POP CX   
    MOV AH,00001111B     
    MOV AL,AH  
    MOV DX,P8255+2              
    OUT DX,AL 
    MOV DL,MIN2                  
    MOV DH,0  
    MOV SI,DX 
    MOV AL,[BX][SI]       
    MOV DX,P8255+1              
    OUT DX,AL 
    MOV AH,00000111B      
    MOV AL,AH  
    MOV DX,P8255+2                
    OUT DX,AL  
    PUSH CX 
    MOV CX,9fffH                
DELAY4:
    nop
    nop 
    LOOP DELAY4       
    POP CX   
    MOV AH,00001111B      
    MOV AL,AH 
    MOV DX,P8255+2               
    OUT DX,AL  
    JMP PLAY
    
    
      
    MOV AH,4CH 
    INT 21H
     
INT_0A PROC NEAR                     
    CMP SEC1,9  
    JZ  INT1  
    INC SEC1 
    JMP EXIT 
INT1:  
    MOV SEC1,0  
    INC SEC2  
    CMP SEC2,6 
    JNZ EXIT 
    MOV SEC2,0 
    INC MIN1  
    CMP MIN1,10 
    JNZ EXIT 
    MOV MIN1,0 
    INC MIN2  
    CMP MIN2,6 
    JNZ EXIT  
    MOV MIN2,0 
EXIT:  
    MOV AL,20H  
    OUT 20H,AL 
    IRET 
INT_0A  ENDP 
CODE ENDS 
END START

五、实验结果与分析

1.本次实验共用了三个芯片,分别是8254,8259,8255。

       8254使用方式3,设定为以10ms为周期的方波发生器,通道0的输入时钟CLK0由实验板上的1MHz振荡器来提供。通道1设定为计数器,输入来自定时器通道0的输出OUT0,利用通道1的计数器输出OUT1作为IRQ3中断请求信号。

       8259用于中断控制器管理。将8254产生的方波连接在IRQ3上,作为中断源。利用DOS系统功能,将IRQ3的终端类型号(0BH)对应的中断向量修改为分、秒计数逻辑函数的段地址和偏移地址,在使用之前打开IRQ3的中断,这样8259每隔一秒便会给CPU发来一个中断并让CPU响应,即跳转到中断程序,修改内存中的分、秒数据。

       8255用来控制LED灯。B口作为LED段选,C口作为LED位选,每次只让一个位置的LED灯亮对应的数字,很短的时间间隔后再让下一位的LED灯亮,循环往复,以较高的频率扫频,通过人眼的视觉暂留来达到LED“同时”亮的效果。

       CPU在8259发来中断时响应中断,改变内存中的分、秒数据。四者联合工作,8254产生方波,8259每隔一秒中给CPU发送一个中断,而8255是由CPU控制的,将CPU内存中的数据在LED灯上显示出来。

2.代码分析

       首先,代码定义了一些数据和设备地址的变量:led 数组是用于存储每个数字对应的LED显示代码的。sec1, sec2, min1, min2 是用于存储秒和分钟的变量,每个变量都存储一位数字。Old_0A 和 Old_8259 是用于存储老的中断向量表和8259中断控制器的值。p8259, p8255, p8253 分别是8259中断控制器,8255并口和8253计时器的IO端口地址。

       代码中的主程序首先初始化数据段,并且将8253计时器和8255并口进行配置。在配置完成后,程序替换了原本的时钟中断处理程序(向量号0Ah),并打开了8259的IRQ0中断。主程序的主循环PLAY中,将秒和分钟的每一位取出,通过查找led数组得到对应的LED代码,然后通过8255并口将这个代码输出到LED显示屏。在每个数字输出之后,程序会暂停一段时间,这段时间通过循环来实现。INT_0A 是自定义的时钟中断处理程序。每次时钟中断,秒的个位数字加一,当秒的个位数字等于9时,秒的十位数字加一,以此类推,当分钟的十位数字等于6时,分钟清零。每次中断处理完成后,发送一个EOI(End Of Interrupt)给8259,然后返回。程序的结束部分,重新加载了原本的时钟中断处理程序,然后使用INT 21H的4CH功能来结束程序。

3.实验细节探究:

       nop 是一个汇编指令,全称 "No Operation"。这个指令在执行的时候什么都不做,CPU会直接跳到下一条指令。nop 通常用于产生微小的延迟或者作为占位符使用。在DELAY1这个标签下的代码中,nop 指令用来创建一个简单的延迟循环。程序会执行 9fffh 次的 nop 指令,每次 nop 都会消耗一点处理器时间,这样一来,9fffh 次 nop 就能创建出一段微小的延迟。这种方式在一些实时性要求比较高的硬件控制程序中比较常见。至于为什么需要延迟,这主要是由于硬件的限制。对于硬件设备来说,它们不能立即响应CPU的指令,需要一定的时间去处理。如果CPU连续发送指令给硬件,而硬件还没来得及处理前一条指令,就可能会导致错误。所以,在操作硬件设备的时候,通常需要插入一些延迟,给硬件设备一些处理时间。在这个程序中,延迟循环是在更新每个LED显示位后进行的,这是为了保证8255并口有足够的时间处理数据的输出,也让LED显示器有足够的时间显示每个数字。如果没有这个延迟,那么LED显示器可能会出现闪烁或者显示错误的问题。

       在这个应用中使用动态扫描显示的方式。动态扫描显示的基本思想是,同时只点亮一个显示单元(在此程序中的一个LED灯),但是由于点亮的速度足够快,人眼无法分辨每个单元是分别点亮的,所以看上去就像所有显示单元都同时亮起。那么,为什么在选中一片 LED 之后,还要再执行一次以下代码:

MOV AH,00001111B     

MOV AL,AH  

MOV DX,P8255+2              

OUT DX,AL 

       这是因为这个命令实际上是关闭(或者说,取消选中)了当前的 LED 灯。这是为了保证在下一个循环开始时,所有的 LED 灯都是处于关闭状态,从而可以重新选择一个 LED 灯进行点亮。既然每次循环都会选择一个 LED 灯进行点亮,为什么还需要显式地关闭所有的 LED 灯呢?这是因为在实际的硬件中,如果不显式地关闭 LED 灯,它可能会由于一些因素(例如,电源噪声或者硬件的电容效应)而继续保持亮起。通过显式地关闭所有的 LED 灯,可以保证显示的正确性。

  • 44
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值