一、任务要求
按下开关K1,七段数码管显示按下的次数(1~9次),当第10次按下时,模拟向INT0输入一次中断,在INT0的中断服务程序INT0PROG中,使用JMP @A+DPTR指令跳转到子程序SUBPROG4执行,在子程序SUBPROG4中,初始化定时器T1的工作方式为2,且工作在计数模式,同时设置相应的计数初值和定时器中断配置,当按下开关K2,使T1计数值自增一次,当T1计数到3*N次时,发生定时器T1中断,在T1中断服务程序T1PROG中,使七段数码管显示字符’S’,显示至少1s后,熄灭。(学号:24,N取4)
二、电路原理图
三、程序流程图
四、汇编代码
ORG 0000H
LJMP BEGIN ; 跳转到BEGIN,程序入口
ORG 0003H ; INT0中断服务程序入口
LJMP INT0PROG ; 跳转到INT0中断服务程序
ORG 0013H ; INT1中断服务程序入口
LJMP INT1PROG ; 跳转到INT1中断服务程序
ORG 001BH ; T1中断服务程序入口
LJMP T1PROG ; 跳转到T1中断服务程序
BEGIN:
SETB EA ; 开启总中断
SETB EX0 ; 打开外部中断0
SETB IT0 ; 设置外部中断0为跳变沿触发方式(下降沿)
SETB EX1 ; 打开外部中断1
SETB IT1 ; 设置外部中断1为跳变沿触发方式(下降沿)
MOV R0, #00H ; 给R0赋初值#00H
MOV P0, #00H ; 将数码管熄灭
CJNE R0, #09H, $ ; 判断外部中断0发生次数是否达到9次,如果没有达到,则继续循环判断,否则跳转到子程序SUBPROG4
LCALL DELAY ; 延长数码管显示字符时间
MOV P0, #00H ; 将数码管熄灭
MOV R0, #00H
MOV A, #00H
MOV DPTR, #SUBPROG4 ; 给子程序SUBPROG4的地址赋值
JMP @A+DPTR ; 通过DPTR和A的值跳转到子程序SUBPROG4
SUBPROG4:
MOV TMOD, #60H ; 初始化定时器T1为工作方式2,计数模式
MOV TH1, #0F5H ; 设置计数初值#0F5H
MOV TL1, #0F5H ; 设置计数初值#0F5H
SETB ET1 ; 允许T1中断
SETB TR1 ; 启动T1
DECIDE:
MOV A, TL1 ; 将TL1寄存器的值赋给A
JNZ DECIDE ; 如果A不为0,则循环判断定时器是否溢出或T1计数是否到12次
SETB TF1 ; 软件置1,表示发生T1中断
LJMP BEGIN ; 程序运行结束,重新开始
INT0PROG:
INC R0 ; R0加1,中断次数加1
MOV DPTR, #TAB ; 给字形表TAB的初始地址赋值给DPTR
MOV A, R0 ; 将要显示的数值存储到A中
MOVC A, @A+DPTR ; 在字形表中找到对应的数值并存储到A中
MOV P0, A ; 将A中的值输出到P0口,用于数码管显示
RETI ; 中断返回指令
INT1PROG:
INC TL1 ; TL1寄存器加1,中断次数加1
RETI ; 中断返回指令
T1PROG:
MOV A, #6DH ; 假设要显示字符'S',将显示S对应的十六进制存储到A中
MOV P0, A ; 将A中的值输出到P0口,用于数码管显示
LCALL DELAY ; 显示字符'S'至少1秒
MOV P0, #00H ; 将P0口输出置为0,熄灭数码管
RETI ; 中断返回指令
DELAY:
PUSH 00H ; 延时子程序
PUSH 01H
PUSH 02H
MOV R0, #80 ; 设置延时循环次数
DELAY1:
MOV R1, #80 ; 设置延时循环次数
DELAY2:
MOV R2, #248 ; 设置延时循环次数
DJNZ R2, $ ; 循环减小R2,直到R2为0
DJNZ R1, DELAY2 ; 循环减小R1,直到R1为0
DJNZ R0, DELAY1 ; 循环减小R0,直到R0为0
POP 02H ; 恢复栈指针
POP 01H
POP 00H
RET ; 返回调用该子程序的指令的下一条指令的地址
TAB:
DB 3FH, 06H, 5BH, 4FH, 66H ; 字形表,0-15对应的数值
DB 6DH, 7DH, 07H, 7FH, 6FH
DB 77H, 7CH, 39H, 5EH, 79H, 71H
END ; 程序结束
五、运行截图
按下第9次,再按下一次就发生中断:
按下12次,显示S字符1s后熄灭: