单片机提高WWW.51C51.COM 自学单片机的网站:作中国单片机编程技术普及推广第一站!倚天一出宝刀屠龙返回主页 给我留言 单片机教程 单片机提高  品质技术 单片机网址软件下载  学液晶显示产品介绍 如何购买

;可预制的倒计时钟,p35个位,p34十位,p32确定
;***************************************************************************
;*  E-mail:sxj1974@163.com (51c51 test web)  51单片机学习网,自学单片机的网站  *
;* Create by :石学军
keyok bit 00h ;是否有键按下的标志
startrun bit 01h ;是否开始运行
value equ 21h ;秒计时值
setval equ 22h ;设置的数值
counter equ 23h ;用于显示的计数器
count equ 24h ;秒计数器
keyval equ 25h ;按键寄存器
dispbuf equ 5eh ;显示缓冲区
first bit p2.5 ;第一个数码管控制
second bit p2.6 ;第二个数码管控制
tmrvar equ 60110 ;定时器的初值65536-5000
hidden equ 0ffh ;显示器的消隐
org 0000h
jmp start
org 1*8+3 ;time0中断入口
jmp int_t0 ;到定时器t0中断服务程序的入口
start:
mov sp,#5fh ; 设置堆栈
mov p1,#0ffh ; 所有led熄灭
mov setval,#59 ;初值59
mov value,setval ;开始不运行,按键后运行
clr startrun
clr keyok ;清除有键按下的标志
mov tmod,#01h
mov th0,#HIGH(TMRVAR) ;取tirvar的高8位
MOV TL0,#LOW(TMRVAR) ; 取tirvar的低8位
SETB ET0 ; 开t0中断
SETB TR0 ;定时器开始运行
; CLR SEC
SETB EA ; 开总中断
LOOP:CALL KEY ;调用键盘程序
JB KEYOK,KEYPROC;如果有键盘按下则转键盘处理
NEXT:MOV A,VALUE ;获得秒的数值
MOV B,#10
DIV AB ;二进制转10进制10位个位分别送显示缓冲
NEXT1:MOV DISPBUF,A ;
MOV DISPBUF+1,B ;个位送显示缓冲
JMP LOOP
KEYPROC:MOV A,KEYVAL ;取得键值
JZ KEYRUN ;如果为0转keyrun
DEC A
JZ KEYSTOP ;如果键值1 转stop
DEC A

JZ KEYLEFT ;如果键值2转left
JMP KEYRIGHT ;如果为3转right
KEYRUN: 
SETB STARTRUN ;将开始运行的标志送1
JMP LOOP
KEYSTOP:
CLR STARTRUN ;开始运行位送0
JMP LOOP
KEYLEFT: ;键盘处理,10位加1并在0-5循环
CLR STARTRUN ;先停止秒
MOV A,SETVAL ;取设置位
ADD A,#10 ;加10
CJNE A,#60,LEFT0 ;到60了么?
MOV A,#0 ;是则清零
JMP LEFT2 ;转left2
LEFT0:JNC LEFT1 ;比60大么, 是则转left1
JMP LEFT2 ; 转left2
LEFT1:SUBB A,#60 ;减60
LEFT2:MOV SETVAL,A ;处理后的a送回setval
MOV VALUE,SETVAL ; 送显示
JMP LOOP
KEYRIGHT: ; 键盘处理,10位加1并在0-5循环
CLR STARTRUN ;先停止秒
INC DISPBUF+1 ;显示器的低位加1
MOV A,DISPBUF+1 ; 送到a
CJNE A,#10,REFT0 ;与10比较不等于则转移
MOV DISPBUF+1,#0 ; 等于10则送0
REFT0:MOV A,DISPBUF ; 取出显示缓冲的高位
MOV B,#10
MUL AB ;乘10
ADD A,DISPBUF+1 ;加低位
MOV SETVAL,A ;送到setval暂存
MOV VALUE,SETVAL ;送显示
JMP LOOP
KEY: ORL P3,#00111100B ;键盘口先送1
CLR KEYOK ;清key标志
MOV A,P3 ;取p3的值
ORL A,#11000011B ;把无关的4位置位
CPL A ;取反a
JZ KEY_RET ;没有按则所有位都是1 取反则为0
CALL DELAY

MOV A,P3 ;再读p3的值
ORL A,#11000011B
CPL A
JZ KEY_RET
SETB KEYOK ;确实有按下
JNB ACC.2,KEY_1 ;s1没有按转key1
MOV KEYVAL,#0 ;如按下则值为0
JMP KEY_RET
KEY_1:JNB ACC.3,KEY_2 ;s1没有按转key2
MOV KEYVAL,#1 ;如按下则值为1
JMP KEY_RET
KEY_2:JNB ACC.4,KEY_3
MOV KEYVAL,#2
JMP KEY_RET
KEY_3:MOV KEYVAL,#3
KEY_RET:
MOV A,P3
ORL A,#11000011B
CPL A
JNZ KEY_RET ;等按键释放
RET
DELAY: mov r5,#2 ;延时20MS
d1:mov r6,#2

D2:djnz r6,d2
djnz r5,d1
ret

INT_T0: ;定时器t0的中断响应
PUSH ACC
PUSH PSW ;压堆栈
MOV TH0,#HIGH(TMRVAR)
MOV TL0,#LOW(TMRVAR)
INC COUNT ;软件计数器加1
MOV A,COUNT ;
CJNE A,#200,INT_N2
MOV COUNT,#0 ;到了200清除
INT_N1:JNB STARTRUN,INT_N2 ; 停止运转,转
DEC VALUE ;计数器减1
MOV A,VALUE
JNZ INT_N2 ; 不为0则转
MOV VALUE,SETVAL ; 否则再置初值
INT_N2:
SETB FIRST
SETB SECOND ;关显示
MOV A,#DISPBUF ; 显示缓冲的首地址
ADD A,COUNTER
MOV R0,A
MOV A,@R0 ;根据计数器的值取相应缓冲的值
MOV DPTR ,#DISPTAB ;字型表的首地址
MOVC A,@A+DPTR
MOV P0,A ; 送显示
MOV A,COUNTER ;取计数器的值
JZ DISPFIRST ; 如果为0则显示第一位
CLR SECOND ; 否则显示第二位
AJMP DISPNEXT
DISPFIRST:
CLR FIRST ;显示第一位
DISPNEXT:
INC COUNTER ;计数器加1
MOV A,COUNTER
DEC A
DEC A ;如果为2则回0
JZ RSTCOUNT
AJMP DISPEXIT
RSTCOUNT:
MOV COUNTER,#0 ;计数器的值只能为0或者1
DISPEXIT:
POP PSW
POP ACC
RETI
DISPTAB:DB 28H,7EH,0A2H,62H,74H,61H,21H,7AH,20H,60H

END