/*
程序效果:1、开机时显示899
2、按键key0一次数字加1,按键key1一次数字减1。
加到999时再加1归零,减到000时再减1得999。
3、按住键key2不放实现连加功能,前3s每0.2s加1,以后每0.1s加1.
4、按住键key3不放实现连减功能,前3s每0.2s减1,以后每0.1s减1.
5、版权所有:http://www.51hei.com/ 转帖须保留
*/
ORG 0000H
LJMP START
ORG 0013H //外部中断1
LJMP IN1
ORG 0030H
START:SETB IT1 //设置为下降沿触发
SETB EX1 //打开外部中断1
SETB EA //开总中断
MOV 30H,#09 //赋初值
MOV 31H,#09
MOV 32H,#08
LOOP: LCALL DISPLAY //调用显示子程序
SJMP LOOP
IN1: LCALL DISPLAY
LCALL DISPLAY
LCALL DELAY1
JB P3.3,LA0P //其实这三条语句就是
LJMP LA0P1 //JB P3.3 LOOP1
LA0P: LJMP LOOP1 //只是跳转距离没有那么大
LA0P1: JNB P3.4 ,KEY0 //KEY0按下,转key0,
//没有则,执行下面的语句
JNB P3.5,KEY1
JNB P3.6,KEY2
JNB P3.7,KEY3
LOOP3: JNB P3.3,LOOP2 //等待P3.3为高
LCALL DISPLAY //为高,调用现实子程序
LCALL DISPLAY
LCALL DELAY1 //延时12ms
JNB P3.3,LOOP3 //P3.3为低,继续等待
LJMP LOOP1 //P3.3为高,结束
LOOP2: LCALL DISPLAY
LJMP LOOP3
KEY0: LCALL ADD1 //KEY0按下,加1
LJMP LOOP3
KEY1: LCALL SUB1 //KEY1按下,加1
LJMP LOOP3
KEY2: MOV R2,#15
LAP2: MOV R1,#33
LCALL ADD1
LAP1: LCALL DISPLAY // 循环完33次约为0.2s
JB P3.3,LAP4 // 33*6ms
DJNZ R1,LAP1 //
DJNZ R2,LAP2 //外循环结束,需3s
//
LAP5: MOV R1,#16
LCALL ADD1
LAP6: LCALL DISPLAY // 循环完16次,需0.1s
JB P3.3,LAP7 // 16*6ms
DJNZ R1, LAP6 //
LJMP LAP5 //快速加1
LAP7: LCALL DISPLAY //P3.3为高,调用显示子程序
LCALL DELAY1
JNB P3.3,LAP6 //P3.3为低,继续快速加1
LJMP LOOP1 //为高,结束
LAP4: LCALL DISPLAY
LCALL DISPLAY
LCALL DELAY1
JNB P3.3,LAP1 //为低,重新循环
LJMP LOOP1 //为高,结束
KEY3: MOV R2,#15 //以下功能同KEY2
LSP2: MOV R1,#33
LCALL SUB1
LSP1: LCALL DISPLAY
JB P3.3,LSP4
DJNZ R1,LSP1
DJNZ R2,LSP2
MOV R1,#16
LCALL SUB1
LSP5: LCALL DISPLAY
JB P3.3,LSP6
DJNZ R1, LSP5
LJMP key3
LSP6: LCALL DISPLAY
LCALL DELAY1
JNB P3.3,LSP5
LJMP LOOP1
LSP4: LCALL DISPLAY
LCALL DISPLAY
LCALL DELAY1
JNB P3.3,LSP1
LOOP1: NOP //空指令
RETI //返回
DISPLAY:MOV DPTR,#TAB //显示没有问题了
MOV A,#0FBH //赋初值
MOV P2,A //点亮第四个数码管
XCH A,R0 //暂存A的值
MOV A,32H
MOVC A,@A+DPTR
MOV P0,A //显示个位数
LCALL DELAY //延时
XCH A,R0
RL A //循环右移,为下次做准备
MOV P2,A
XCH A,R0
MOV A,31H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELAY
XCH A,R0
RL A
MOV P2,A
MOV A,30H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELAY
RET
ADD1: INC 30H //加1子程序
MOV A,30H
CJNE A,#10,LOP1 //判断个位是否满10
MOV 30H,#00 //是,则清零
INC 31H //同时十位加1
MOV A,31H
CJNE A,#10,LOP1 //判断十位是否满10
MOV 31H,#00 //是,则清零
INC 32H //同时百位加1
MOV A,32H
CJNE A,#10,LOP1 //判断百位是否满10
MOV 32H,#00 //是,则清零
LOP1: NOP //空指令
RET //返回
SUB1: DEC 30H //减1子程序
MOV A,30H
CJNE A,#0FFH,LOP2 //判断是否减过0
MOV 30H,#09 //是,则赋9
DEC 31H
MOV A,31H
CJNE A,#0FFH,LOP2
MOV 31H,#09
DEC 32H
MOV A,32H
CJNE A,#0FFH,LOP2
MOV 32H,#09
LOP2: NOP
RET
TAB: DB 3FH,06H,5BH,4FH,66H ;数码管显示的数值
DB 6DH,7DH,07H,7FH,6FH
DELAY: MOV R7,#4 //延时时间约为:2MS
DEL2: MOV R6,#250
DEL1: DJNZ R6,DEL1
DJNZ R7,DEL2
RET
DELAY1: MOV R7,#24 //延时时间约为:12MS
DEL3: MOV R6,#250
DEL4: DJNZ R6,DEL4
DJNZ R7,DEL3
RET
END