$INCLUDE (C8051F020.INC)
;P1口输出BCD码, P2口的0,1,2,3输出位地址数据,P2口的5,6分别为设置键,P2口的7键为输出键 低电平有效
;----------------------------------------------
SELECT_KEY EQU P2.5 ;位置选择键
T_KEY EQU P2.6 ;调整键
JDQ EQU P2.7 ;输出键
S_DATA DATA 50H ;秒
M_DATA DATA 51H ;分
H_DATA DATA 52H ;时
T_DATA DATA 53H ;计数器
;程序从0000H单元开始
ORG 0000H
LJMP MAIN
;------------------------------------------
;设置中断跳转程序地址入口
ORG 000BH;T0定时中断0入口地址
LJMP DS0ZD;跳转到T0中断程序
;-------------------------------------------
;主程序开始设置各个寄存器和初始值,使之按一定的要求来完成
MAIN:
MOV OSCXCN,#66H
MOV WDTCN,#0DEH
MOV WDTCN,#0ADH
MOV XBR0,#04H
MOV XBR1,#1EH
MOV XBR2,#40H
MOV P1MDOUT,#0FFH;两口复位
MOV P2MDOUT,#0FFH
MOV CKCON,#08H
MOV OSCICN,#08H
WAIT:
MOV A,OSCXCN
JNB ACC.7,WAIT
MOV SP,#70H
MOV R0,#00H
MOV R1,#00H
MOV R2,#00H ;秒个位
MOV R3,#00H ;秒十位
MOV R4,#00H ;分个位
MOV R5,#00H ;分十位
MOV R6,#00H ;时个位
MOV R7,#00H ;时十位
MOV S_DATA,#00H
MOV M_DATA,#00H
MOV H_DATA,#00H
MOV T_DATA,#00H
MOV TMOD,#02H ;T0采用方式2 自动装载
MOV TL0,#06H ;定时器初值
MOV TH0,#06H
SETB EA
SETB ET0
SETB TR0
;********************循环程序开始************************
START:
LCALL FEN
LCALL XSCX00
LCALL KEY
;LCALL CONTROL
AJMP START
;-------------------------------------------------
FEN:
MOV A,S_DATA
LCALL HEX_BCD
MOV R3,A
MOV R2,B
;
MOV A,M_DATA
LCALL HEX_BCD
MOV R5,A
MOV R4,B
;
MOV A,H_DATA
LCALL HEX_BCD
MOV R7,A
MOV R6,B
RET
;-------------------------------------------------
;显示程序开始1
XSCX00:;显示程序,将需要显示的位数和需要显示的数据起始地址写入再将BCD码表写入DPTR
PUSH ACC
MOV A,#00H
MOV R0,#02H;将要显示数据的起始地址写入R0(这里是从分钟开始)
MOV DPTR,#ZB0;将LED码表写入DPTR
MOV R1,#04H;将所需要的显示位数写入R1
XSCX01:
MOV A,@R0;将数据传到A
MOVC A,@A+DPTR;将所需要显示的BCD码写入A
MOV P1,A;将BCD码传到P1口
MOV A,P2;将位地址读入A
CJNE A,#0FFH,GUO;检查位地址是0FFH,若不是则跳过,若是运行下一步
MOV P2,#01H;将第一位传到P2口
LJMP TIAOGUO;跳转到TIAOGUO
GUO:
RL A;A中内容左移一位
MOV P2,A;将位地址传出到P2口
TIAOGUO:
LCALL YS0
INC R0
DJNZ R1,XSCX01
MOV P2,#0FFH
POP ACC
RET
;---------------------------------------------
;-------------------------------------------------
;显示程序开始2 只显示分钟,不显示小时
XSCX01:;显示程序,将需要显示的位数和需要显示的数据起始地址写入再将BCD码表写入DPTR
PUSH ACC
MOV A,#00H
MOV R0,#02H;将要显示数据的起始地址写入R0(这里是从分钟开始)
MOV DPTR,#ZB0;将LED码表写入DPTR
MOV R1,#02H;将所需要的显示位数写入R1
XSCX01:
MOV A,@R0;将数据传到A
MOVC A,@A+DPTR;将所需要显示的BCD码写入A
MOV P1,A;将BCD码传到P1口
MOV A,P2;将位地址读入A
CJNE A,#0FFH,GUO;检查位地址是0FFH,若不是则跳过,若是运行下一步
MOV P2,#01H;将第一位传到P2口
LJMP TIAOGUO;跳转到TIAOGUO
GUO:
RL A;A中内容左移一位
MOV P2,A;将位地址传出到P2口
TIAOGUO:
LCALL YS0
INC R0
DJNZ R1,XSCX01
MOV P2,#0FFH
POP ACC
RET
;---------------------------------------------
;-------------------------------------------------
;显示程序开始3 只显示小时,不显示分钟
XSCX03:;显示程序,将需要显示的位数和需要显示的数据起始地址写入再将BCD码表写入DPTR
PUSH ACC
MOV A,#00H
MOV R0,#02H;将要显示数据的起始地址写入R0(这里是从分钟开始)
MOV DPTR,#ZB0;将LED码表写入DPTR
MOV R1,#02H;将所需要的显示位数写入R1
XSCX01:
MOV A,@R0;将数据传到A
MOVC A,@A+DPTR;将所需要显示的BCD码写入A
MOV P1,A;将BCD码传到P1口
MOV A,P2;将位地址读入A
CJNE A,#0FFH,GUO;检查位地址是0FFH,若不是则跳过,若是运行下一步
MOV P2,#08H;将第一位传到P2口
LJMP TIAOGUO;跳转到TIAOGUO
GUO:
RR A;A中内容左移一位
MOV P2,A;将位地址传出到P2口
TIAOGUO:
LCALL YS0
INC R0
DJNZ R1,XSCX01
MOV P2,#0FFH
POP ACC
RET
;---------------------------------------------
;T0中断子程序开始
;产生秒信号
DS0ZD: ;主中断程序(时基)
PUSH ACC
PUSH PSW
CLR TR0
MOV TL0,#06H ;T0的产生0.5MS
MOV TH0,#06H
SETB TR0
INC 5DH
MOV A,5DH
CJNE A,#14H,D0
MOV 5DH,#00H ;循环20次 10MS
INC 5FH
MOV A,5FH
CJNE A,#64H,D0
MOV 5FH,#00H ;循环100次 1S
MOV A,S_DATA
ADD A,#01H
MOV S_DATA,A
CJNE A,#60,D0
MOV S_DATA,#00H
MOV A,M_DATA
ADD A,#01H
MOV M_DATA,A
CJNE A,#60,D0
MOV M_DATA,#00H
MOV A,H_DATA
ADD A,#01H
MOV H_DATA,A
CJNE A,#24,D0
MOV H_DATA,#00H
D0: POP PSW ;T0中断结束
POP ACC
RETI
;T0中断结束
;------------------------------------------------
;延时子程序,共延时约100MS
YS0:;延时约100MS
MOV B,#0FFH;0FFH
YS01:
DJNZ B,YS01
RET
;------------------------------------------------
;共阳BCD码表从0 到9
ZB0:;共阳BCD码表
DB 40H,11110010B,88H,10100000B,32H,24H,04H,11110000B,00H,20H
;------------------------------------------------
;***************KEY(键盘调整时间) PROGRAM ***************
KEY:
JB SELECT_KEY,D0
LCALL YS0
JB SELECT_KEY,D0
INC T_DATA
D0: MOV A,T_DATA
CJNE A,#00H,S_END0 ;恢复走时
LJMP S_END
S_END0:
CJNE A, #01H,H_SET1 ;小时选择位
LJMP H_SET
H_SET1:
CJNE A,#02H,M_SET1 ;分钟选择位
LJMP M_SET
M_SET1:
MOV T_DATA,#00H
LJMP S_END
M_SET:
JB T_KEY,S_END1
LCALL YS0
JB T_KEY, S_END1
INC M_DATA
MOV A,M_DATA
CJNE A,#60,M_DIS
MOV M_DATA,#00H
M_DIS:
MOV A,M_DATA
LCALL HEX_BCD
MOV R5,A
MOV R4,B
S_END1:
LCALL XSCX01
LJMP S_END
H_SET:
JB T_KEY,S_END2
LCALL YS0
JB T_KEY,S_END2
INC H_DATA
MOV A,H_DATA
CJNE A,#24,H_DIS
MOV H_DATA,#00H
H_DIS:
MOV A,H_DATA
LCALL HEX_BCD
MOV R7,A
MOV R6,B
S_END2:
LCALL XSCX02
S_END:
RET
;--------------------------------------------------------
;******************定时程序CONTROL JDQ*********8
CONTROL:
MOV A,H_DATA
XRL A,#12 ;设置时间小时
JZ M_CONT
AJMP C_END
M_CONT:
MOV A,M_DATA
XRL A,#30 ;设置时间分钟
JZ OPEN_JDQ
AJMP OVER_JDQ
OPEN_JDQ:CLR JDQ
AJMP C_END
OVER_JDQ:MOV A,M_DATA
XRL A,#40
JNZ C_END
SETB JDQ
C_END:RET
;************HEX_BCD 转换子程序*******8
HEX_BCD:MOV B,#10
DIV AB ;A=13 命令执行后 A=1 B=3
RET
END