微机原理课程设计
设计题目:利用8259A的IRQ2显示中断过程
学生姓名:王瑞(20042412)
指导老师:周国祥
实验时间:2007年1月
设计题目:
利用8259A的 IRQ2显示中断过程
要求:
1.
主程序是在七段数码管上循环显示‘8’,从右到左显示。
2.
中断服务程序中,在七段数码管上依次显示全1,2,3,4,5,6,7, 8,9要去显示2秒左右的时间,可采用软件延迟(时间可通过调试大致2秒左右),总计中断9次,结束返回DOS。
3.
每次由手动产生IRQ2中断请求信号,引起中断。
设计思路:
软件方面,程序有两个主要部分:主程序和中断服务子程序。
主程序首先要完成的是一些与处理工作,例如查找设备,设置TPC卡中 9054芯片IO口,保存原来的0AH号中断的中断向量,设置新的中断向量,设置中断掩码,显示提示信息,然后打开中断,进入主循环。在主循环中,不断的在LED上从右向左显示8。直到被IRQ2的中断信号打断。此外,在主程序中还对中断的执行进行计数。当计数满9次后,自动跳出。为了使主程序上的8的循环可以看的出来,故将显示8的延迟设计的比较长。当完成9次中断,主程序还要完成一些后续的处理工作:恢复中断掩码;恢复中断向量;设置 TPC卡中9054芯片IO口,关闭中断。返回DOS。
中断子程序完成在6位数码管上“同时”显示一个数的功能,这个数为1—9中的某一个,可以用循环次数作为参数。这里的同时显示实质上是利用视觉上的暂停效果,即只要每秒能在同一个数码管上显示信息超过24次,看起来就是同时了。而这一点在现在的计算机速度条件下很容易实现。为了不发生混乱,在中断子程序的执行过程中不允许再次中断。
另外,程序中还有两个子程序:findtpc和dispword,这些是为了完成查找设备等预处理。
硬件方面,实验时把总线上的IRQ2引脚与拨键开关相连以手动的产生中断信号。另外,再把LED的片选信号CS与210-217相连。(注:LED的显示是通过向LED的数据端口送入数据,再向LED的位选端口送入位选信号来实现)
实验程序:
;386
以上微机适用
;
纯
dos
下才能使用
;tasm4.1
或以上编译
;**********************************************;
;*
利用
8259A
的
IRQ2
显示中断过程
*;
;**********************************************;
io_plx_device_id equ 05406h ;TPC
卡设备
ID
io_plx_vendor_id equ 010b5h ;TPC
卡厂商
ID
IO_PLX_SUB_ID EQU 0905410B5H ;TPC
卡子设备及厂商
ID
portseg EQU 211H-200H ;
数码管端口地址
portbit EQU 210H-200H
data segment
csreg dw ?
ipreg dw ? ;
旧中断向量保存空间
irq_times dw 10 ;
中断计数
msg1 db 0dh,0ah,'TPC pci card Interrupt',0dh,0ah,'$'
msg2 db 0dh,0ah,'Press any key to exit!',0dh,0ah,'$'
msg3 db 0dh,0ah,'Press DMC or wait to interrupt 10 times and exit!',0dh,0ah,'$'
io_9054base_address db 4 DUP(0) ;TPC
卡
PCI
接口芯片
I/O
基地址暂存空间
io_base_address db 4 DUP(0) ;TPC
卡
I/O
基地址暂存空间
interrupt_line db 2 DUP(0) ;TPC
卡中断号暂存空间
pcicardnotfind db 0dh,0ah,'TPC pci card not find or address/interrupt error !!!',0dh,0ah,'$'
io9054baseaddress db 0dh,0ah,'TPC pci card 9054 Chip I/O Base Address : ','$'
iobaseaddress db 0dh,0ah,'TPC pci card I/O Base Address : ','$'
intnumber db 0dh,0ah,'TPC pci card Interrupt Line : ','$'
enter_return db 0dh,0ah,'$'
MESS DB '8253A TIMER0 IN MODE3! COUNT=0200H',0AH,0DH
DB '8253A TIMER1 IN MODE2! COUNT=0aH',0AH,0DH,'$'
irq_vect db 08h,09h,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
;
新的中断向量
,
中断
0-7
的向量为
:08h-0fh,
中断
8-15
的向量为
:70h-77h
irq_mask_0_7_table db 011111110b,011111101b,011111011b,011110111b
db 011101111b,011011111b,010111111b,001111111b
db 011111011b,011111011b,011111011b,011111011b
db 011111011b,011111011b,011111011b,011111011b
;
新的中断掩码
,
中断
0-7
时从低至高相应位为零
,
中断
8-15
时第
2
位为零
irq_mask_8_15_table db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh
db 011111110b,011111101b,011111011b,011110111b
db 011101111b,011011111b,010111111b,001111111b
;
新的中断掩码
,
中断
0-7
时全一
,
中断
8-15
时从低至高相应位为零
LED DB 06,5BH,4FH,66H,6DH,7DH,07,7FH,6FH
data ends
stacks segment
db 100 dup (?)
stacks ends
code segment
assume cs:code,ds:data,ss:stacks,es:data
start:
;Enable Local Interrupt Input
.386
cli
mov ax,data
mov ds,ax
mov es,ax
mov ax,stacks
mov ss,ax
call findtpc ;
查找
TPC
卡资源并显示
mov dx,word ptr io_9054base_address
add dx,68h ;
设置
tpc
卡中
9054
芯片
io
口
,
使能中断
in ax,dx
or ax,0900h
out dx,ax
mov bx,word ptr interrupt_line ;
保存原中断向量
mov al,byte ptr [irq_vect+bx]
mov ah,35h
int 21h
mov ax,es
mov csreg,ax
mov ipreg,bx
mov bx,word ptr interrupt_line ;
设置新中断向量
mov al,byte ptr [irq_vect+bx]
mov cx,cs
mov ds,cx
mov dx,offset int_proc
mov ah,25h
int 21h
mov ax,data
mov ds,ax
mov es,ax
in al, 21h ;
设置中断掩码
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_0_7_table+bx]
and al,ah
out 21h, al
in al, 0a1h
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_8_15_table+bx]
and al,ah
out 0a1h, al
mov dx,offset msg2
mov ah,09h
int 21h
mov dx,offset msg3
mov ah,09h
int 21h
mov irq_times,0
sti ;
开中断
loop1:
cmp irq_times,9 ;
等待中断并判断中断
9
次后退出
jz exit
mov ax,data
mov ds,ax
mov al,7FH
mov dx,word ptr io_base_address
add dx,portseg
out dx,al
mov al,bl
mov dx,word ptr io_base_address
add dx,portbit
out dx,al
push cx
mov cx,0FFFFh
skip3:
push cx
mov cx,03FFH
skip4:
loop skip4
pop cx
loop skip3
pop cx
shl bl,1
cmp bl,40h
jne skip5
mov bl,01h
skip5:
jmp loop1
exit:
cli
mov bx,word ptr interrupt_line ;
恢复中断掩码
mov ah,byte ptr [irq_mask_0_7_table+bx]
not ah
in al, 21h
or al, ah
out 21h, al
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_8_15_table+bx]
not ah
in al, 0a1h
or al, ah
out 0a1h, al
mov bx,word ptr interrupt_line ;
恢复原中断向量
mov al,byte ptr [irq_vect+bx]
mov dx,ipreg
mov cx,csreg
mov ds,cx
mov ah,25h
int 21h
mov ax,data ;
设置
tpc
卡中
9054
芯片
io
口
,
关闭中断
mov ds,ax
mov dx,word ptr io_9054base_address
add dx,68h
in ax,dx
and ax,0f7ffh
out dx,ax
mov ax,4c00h
int 21h ;
退出
int_proc proc far
cli
push ax
push dx
push ds
mov bl,01h
mov ax,data
mov ds,ax
mov si,irq_times
mov cx,05FFH
again:
mov al,LED[si]
mov dx,word ptr io_base_address
add dx,portseg
out dx,al
mov al,bl
mov dx,word ptr io_base_address
add dx,portbit
out dx,al
shl bl,1
cmp bl,40h
jne skip6
mov bl,01h
skip6:
push cx
mov cx,0FFFFH
again2:
push cx
mov cx,10
again4:
loop again4
pop cx
loop again2
pop cx
loop again
mov al,20h ;Send EOI
out 0a0h,al
out 20h,al
inc irq_times
pop ds
pop dx
pop ax
sti
iret
int_proc endp
findtpc proc near ;
查找
TPC
卡资源并显示
pushad
pushfd
mov ax,0b101h
int 1ah
jc findtpc_notfind ;
检查
PCI BIOS
是否存在
mov ax,0b102h
mov cx,io_plx_device_id
mov dx,io_plx_vendor_id
mov si,0
int 1ah
jc findtpc_notfind ;
检查
tpc
卡是否安装
,
设备号、厂商号
mov ax,0b10ah
mov di,02ch
int 1ah
jc findtpc_notfind
cmp ecx,io_plx_sub_id
jnz findtpc_notfind ;
检查
tpc
卡是否安装
,
子设备号、厂商号
mov ax,0b10ah
mov di,14h
int 1ah
jc findtpc_notfind ;
读
TPC
卡
9054
芯片
I/O
基址信息
mov dword ptr io_9054base_address,ecx
and ecx,1
jz findtpc_notfind ;
检查是否为
i/o
基址信息
mov ecx,dword ptr io_9054base_address
and ecx,0fffffffeh
mov dword ptr io_9054base_address,ecx ;
去除
i/o
指示位并保存
MOV AX,0B10AH
MOV DI,18H
INT 1AH
JC findtpc_notfind ;
读
TPC
卡
I/O
基址信息
mov dword ptr io_base_address,ecx
and ecx,1
jz findtpc_notfind ;
检查是否为
i/o
基址信息
mov ecx,dword ptr io_base_address
and ecx,0fffffffeh
mov dword ptr io_base_address,ecx ;
去除
i/o
指示位并保存
mov ax,0b10ah
mov di,3ch
int 1ah
jc findtpc_notfind ;
读
TPC
卡中断信息
and cx,0ffh
mov word ptr interrupt_line,cx ;
去除
interrupt
其它指示位并保存
mov dx,offset io9054baseaddress ;
显示
i/o
提示信息
mov ah,09h
int 21h
mov ax,word ptr io_9054base_address
call dispword ;
显示
i/o
基地址
mov dx,offset iobaseaddress ;
显示
i/o
提示信息
mov ah,09h
int 21h
mov ax,word ptr io_base_address
call dispword ;
显示
i/o
基地址
mov dx,offset intnumber ;
显示
interrupt
提示信息
mov ah,09h
int 21h
mov ax,word ptr interrupt_line
call dispword ;
显示中断号
mov dx,offset enter_return ;
加回车符
,
换行符
mov ah,09h
int 21h
popfd
popad
ret
findtpc_notfind:
mov dx,offset pcicardnotfind ;
显示未找到
tpc
卡提示信息
mov ah,09h
int 21h
mov ax,4c00h
int 21h ;
退出
findtpc endp
dispword proc near ;
显示子程序
push dx
push cx
push bx
mov cx,4
mov bx,16
dispword_loop1:
push ax
push cx
sub bx,4
mov cx,bx
shr ax,cl
and al,0fh ;
首先取低四位
mov dl,al
cmp dl,9 ;
判断是否
<=9
jle dispword_num ;
若是则为
'0'-'9',ASCII
码加
30H
add dl,7 ;
否则为
'A'-'F',ASCII
码加
37H
dispword_num:
add dl,30h
mov ah,02h ;
显示
int 21h
pop cx
pop ax
loop dispword_loop1
pop bx
pop cx
pop dx
ret ;
子程序返回
dispword endp
code ends
end start
实验心得:
本实验的难点在
LED
的显示上,由于在此之前,我一直认为
LED
的显示是由
8255A
驱动,所以一开始做这个程序时,我首先想到的是利用
8255A
。但是结合实验箱上的
LED
我才发现这样的方法行不同。于是,再回头认真的学习了一下
LED
的显示原理。才发现
LED
的显示其实很简单。只要往数据端口送数据,再往位选端口送入位选代码就可以了。这下程序流程变得豁然开朗。另外,在设计的时候,我和其他同学讨论了手动中断信号的种种产生方式,最终发现用开关直接与总线插槽上的
IRQ2
直接相连时最简单的方法!本实验的一些预处理操作和有关
TPC
实验板的初始化、后处理,都是结合平时实验的程序,在此基础上修改完成的。经过小组成员的一致努力,我们圆满的完成了这次的实验任务!经过此次实验,我体验了从实践到学习再到实践的过程的乐趣。