求AT89S52单片机 数字钟 汇编程序,要求能正常显示时分秒,能校时校分,能用的我加分! 100
KEYVAL EQU 30H
KEYTM EQU 31H
KEYSCAN EQU 32H
DAT EQU 33H
SCANLED EQU 39H
CLK EQU 77H
SEC EQU 78H
MIN EQU 79H
HOUR EQU 7AH
PAUSE BIT 00H
DOT BIT 01H
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0ISR ;50ms定时
ORG 001BH
LJMP T1ISR ;扫描显示
ORG 0030H
MAIN:
MOV SP,#5FH
MOV TMOD,#11H
MOV TH0,#03CH
MOV TL0,#0B0H
MOV TH1,#0ECH
MOV TL1,#078H
MOV KEYVAL,#0
MOV SCANLED,#0
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV 37H,#10H
MOV 38H,#10H
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
MOV CLK,#0
CLR PAUSE
SETB EA
SETB ET1
SETB TR1
LOOP:
LCALL KEYSEL
MOV A,KEYVAL
CJNE A,#0FFH,LOOP1
SJMP LOOP
LOOP1:
CJNE A,#10,LOOP2 ;“ON”启动
SETB TR0
SETB ET0
SETB PAUSE
SJMP LOOP
LOOP2:
CJNE A,#11,LOOP3 ;“=”清零
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
LCALL DISCHG
SJMP LOOP
LOOP3:
CJNE A,#15,LOOP4 ;“+”暂停
CLR TR0
CLR ET0
CLR PAUSE
SJMP LOOP
LOOP4:
CJNE A,#14,LOOP5 ;“-”清显示暂停
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV 37H,#10H
MOV 38H,#10H
CLR TR0
CLR ET0
CLR PAUSE
SJMP LOOP
LOOP5:
CJNE A,#10,LOOP6 ;数字键
LOOP6:
JC LOOP7
LJMP LOOP
LOOP7:
JNB PAUSE,LOOP8 ;暂停状态可以输入数字键
LJMP LOOP
LOOP8:
MOV 33H,34H
MOV 34H,35H
MOV 35H,36H
MOV 36H,37H
MOV 37H,38H
MOV 38H,KEYVAL
MOV A,33H
SWAP A
ORL A,34H
LCALL BCDH
MOV HOUR,A
MOV A,35H
SWAP A
ORL A,36H
LCALL BCDH
MOV MIN,A
MOV A,37H
SWAP A
ORL A,38H
LCALL BCDH
MOV SEC,A
LJMP LOOP
;------------------
;BCD转换为十六进制
BCDH:
MOV B,#10H
DIV AB
MOV R7,B
MOV B,#10
MUL AB
ADD A,R7
RET
;------------------
;十六进制转换为BCD
HBCD:
MOV B,#10
DIV AB
SWAP A
ORL A,B
RET
;------------------
KEYSEL:
MOV KEYVAL,#0
MOV KEYSCAN,#0EFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS1
MOV KEYVAL,A
SJMP KEYRTN
KEYS1:
MOV KEYSCAN,#0DFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS2
CLR C
ADD A,#4
MOV KEYVAL,A
SJMP KEYRTN
KEYS2:
MOV KEYSCAN,#0BFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS3
CLR C
ADD A,#8
MOV KEYVAL,A
SJMP KEYRTN
KEYS3:
MOV KEYSCAN,#7FH
LCALL GETKEY
MOV A,KEYTM
JZ KEYRTN
CLR C
ADD A,#12
MOV KEYVAL,A
KEYRTN:
LCALL CHGKEY
RET
;--------------------
GETKEY:
MOV KEYTM,#0
MOV A,KEYSCAN
MOV P3,A
NOP
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV R2,#10
LCALL DELAY
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV A,P3
ANL A,#0FH
MOV R7,A
SF:
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ SF
MOV A,R7
CJNE A,#0EH,NK1
MOV KEYTM,#1
SJMP NOKEY
NK1:
CJNE A,#0DH,NK2
MOV KEYTM,#2
SJMP NOKEY
NK2:
CJNE A,#0BH,NK3
MOV KEYTM,#3
SJMP NOKEY
NK3:
CJNE A,#07H,NOKEY
MOV KEYTM,#4
NOKEY: RET
;--------------------
DELAY:
MOV R3,#50
DELAY1:
MOV R4,#100
DJNZ R4,$
DJNZ R3,DELAY1
DJNZ R2,DELAY
RET
;--------------------
T0ISR:
PUSH ACC
CLR TR0
MOV TH0,#3CH
MOV TL0,#0B0H
SETB TR0
INC CLK
MOV A,CLK
CJNE A,#20,T0ISRE
MOV CLK,#0
INC SEC
MOV A,SEC
CJNE A,#60,T0ISRE
MOV SEC,#0
INC MIN
MOV A,MIN
CJNE A,#60,T0ISRE
MOV MIN,#0
INC HOUR
MOV A,HOUR
CJNE A,#24,T0ISRE
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
T0ISRE:
LCALL DISCHG
POP ACC
RETI
;--------------------
DISCHG:
MOV A,HOUR
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 34H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 33H,A
MOV A,MIN
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 36H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 35H,A
MOV A,SEC
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 38H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 37H,A
RET
;--------------------
T1ISR:
PUSH ACC
CLR TR1
MOV TH1,#0ECH
MOV TL1,#78H
SETB TR1
MOV DPTR,#LEDTAB
T100:
MOV R0,#DAT
MOV A,SCANLED
ADD A,R0
MOV R0,A
MOV A,SCANLED
JNZ T101
MOV P2,#01H
CLR DOT
SJMP T1DIS
T101:
DEC A
JNZ T102
MOV P2,#02H
SETB DOT
SJMP T1DIS
T102:
DEC A
JNZ T103
MOV P2,#04H
CLR DOT
SJMP T1DIS
T103:
DEC A
JNZ T104
MOV P2,#08H
SETB DOT
SJMP T1DIS
T104:
DEC A
JNZ T105
MOV P2,#10H
CLR DOT
SJMP T1DIS
T105:
MOV P2,#20H
CLR DOT
T1DIS:
MOV A,@R0
MOVC A,@A+DPTR
JNB DOT,T1DIS1
ORL A,#01H
T1DIS1:
CPL A
MOV P0,A
INC SCANLED
MOV A,SCANLED
CJNE A,#6,T1END
MOV SCANLED,#0
T1END:
POP ACC
RETI
;--------------------
CHGKEY:
MOV A,KEYVAL
JZ KV16
DEC A
JNZ KV01
MOV KEYVAL,#7
RET
KV01:
DEC A
JNZ KV02
MOV KEYVAL,#4
RET
KV02:
DEC A
JNZ KV03
MOV KEYVAL,#1
RET
KV03:
DEC A
JNZ KV04
MOV KEYVAL,#10
RET
KV04:
DEC A
JNZ KV05
MOV KEYVAL,#8
RET
KV05:
DEC A
JNZ KV06
MOV KEYVAL,#5
RET
KV06:
DEC A
JNZ KV07
MOV KEYVAL,#2
RET
KV07:
DEC A
JNZ KV08
MOV KEYVAL,#0
RET
KV08:
DEC A
JNZ KV09
MOV KEYVAL,#9
RET
KV09:
DEC A
JNZ KV10
MOV KEYVAL,#6
RET
KV10:
DEC A
JNZ KV11
MOV KEYVAL,#3
RET
KV11:
DEC A
JNZ KV12
MOV KEYVAL,#11
RET
KV12:
DEC A
JNZ KV13
MOV KEYVAL,#12
RET
KV13:
DEC A
JNZ KV14
MOV KEYVAL,#13
RET
KV14:
DEC A
JNZ KV15
MOV KEYVAL,#14
RET
KV15:
DEC A
JNZ KV16
MOV KEYVAL,#15
RET
KV16:
MOV KEYVAL,#0FFH
RET
;--------------------
LEDTAB: DB 0FCH ;"0" 00H
DB 60H ;"1" 01H
DB 0DAH ;"2" 02H
DB 0F2H ;"3" 03H
DB 66H ;"4" 04H
DB 0B6H ;"5" 05H
DB 0BEH ;"6" 06H
DB 0E0H ;"7" 07H
DB 0FEH ;"8" 08H
DB 0F6H ;"9" 09H
DB 0EEH ;"A" 0AH
DB 3EH ;"B" 0BH
DB 9CH ;"C" 0CH
DB 7AH ;"D" 0DH
DB 9EH ;"E" 0EH
DB 8EH ;"F" 0FH
DB 00H ;" " 10H
;--------------------
END
示指示灯端口,P2.4为按键1(进入调整时间模式,指示灯闪烁一次),P2.5为按键2(分钟加),P2.6
、为按键3(小时加),P2.7为按键4(退出--->调整时间模式)。在走时钟状态时直接按按键K2(指
示灯闪烁三次),则进入定时时钟设置模式--->K1按键小时加,K3按键分钟加,K4按键退出定时设置模
式 在正常走时过程中,按下按键K2确定设置或取消闹铃(指示灯常亮表示有闹铃,反之……),按键K4
取消正在响铃,使时钟继续走。*/
HOUR EQU 31H
MIN EQU 32H
SEC EQU 33H
SMG_SUF EQU 34H
SMG_SHIFT EQU 3CH //偏移量
SMG_WI EQU 3DH
T_COUNT EQU 3FH
TIMED_HOUR EQU 40H //定时存储单元--->小时
TIMED_MIN EQU 41H //定时存储单元--->分钟
TIMED_SEC EQU 42H //定式存储单元--->秒
LATCH_A BIT P2.3
LATCH_B BIT P2.2
K1 BIT P2.4 //按键1 进入调时模式
K2 BIT P2.5 //按键2 使分钟加1
K3 BIT P2.6 //按键3 使小时加1
K4 BIT P2.7 //按键4 退出调试模式
BELL BIT P3.7 //蜂鸣器
LED BIT P3.6 //按键指示灯
BELL_FLAG BIT 20H.0 //定时确定与取消
ORG 0000H
AJMP MAIN
ORG 000BH
AJMP TIME0
ORG 001BH
AJMP TIME1
ORG 0030H
MAIN: MOV SP,#70H
MOV HOUR,#12
MOV MIN,#0
MOV SEC,#0
MOV SMG_SUF+2,#10
MOV SMG_SUF+5,#10
MOV SMG_SHIFT,#0
MOV SMG_WI,#0FEH
MOV T_COUNT,#0
MOV TIMED_HOUR,#0 //定时 时 时间存储
MOV TIMED_MIN,#0 //定时 分 时间存储
MOV TIMED_SEC,#0 //定时 秒 时间存储
ACALL INIT_T0T1
SETB BELL
SETB LED
SETB BELL_FLAG
START: ACALL CONV
JB BELL_FLAG,BQ_NEXT//标志位为1则转移,不查询定时程序
CLR LED //设置则不断闪
ACALL TIMEING //定时子程序查询
BQ_NEXT: JB K1,KEY2 //如果为未按K3按键,则闹铃设置,再按则取消
ACALL DELAY_10MS
JB K1,KEY2
JNB K1,$
ACALL LIGHT
ACALL KEY_PROC
AJMP START
KEY2: JB K2,KEY3
ACALL DELAY_10MS
JB K2,KEY3
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
JNB K2,$
ACALL BELL_SET
AJMP START
KEY3: JB K3,KEY4
ACALL DELAY_10MS
JB K3,KEY4
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
JNB K3,$
CPL BELL_FLAG //取反 ---> (默认是 1)按键3控制着闹钟标志位
AJMP START
KEY4: JB K4,NEXT
NEXT: AJMP START
//转换子程序
CONV: MOV A,HOUR
MOV B,#10
DIV AB
MOV SMG_SUF,A
MOV A,B
MOV SMG_SUF+1,A
MOV A,MIN
MOV B,#10
DIV AB
MOV SMG_SUF+3,A
MOV A,B
MOV SMG_SUF+4,A
MOV A,SEC
MOV B,#10
DIV AB
MOV SMG_SUF+6,A
MOV A,B
MOV SMG_SUF+7,A
RET
//显示子程序
DISP: MOV P0,#0FFH /* 这一句话是后来发现出现“鬼影”之后加上去的,每一次扫描完都熄灭一次 */
SETB LATCH_A
CLR LATCH_A
MOV A,#SMG_SUF
ADD A,SMG_SHIFT //偏移量+基地址
MOV R0,A //偏移量+基地址=物理地址存到R0中
MOV A,@R0 //取出物理地址的值传给A
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
SETB LATCH_B
CLR LATCH_B
MOV P0,SMG_WI
SETB LATCH_A
CLR LATCH_A
INC SMG_SHIFT
MOV A,SMG_SHIFT
CJNE A,#8,DISP_NEXT
MOV SMG_SHIFT,#0
DISP_NEXT: MOV A,SMG_WI
RL A
MOV SMG_WI,A
RET
//定时器0初始化程序
INIT_T0T1: MOV TMOD,#11H //定义两个定时器
MOV TH0,#0F8H //对定时器0赋初值
MOV TL0,#30H
MOV TH1,#3CH //对定时器1赋初值
MOV TL1,#0B0H
SETB EA //开启总中断
SETB ET0 //定时器0
SETB ET1 //定时器1
SETB TR0 //开启定时器0
SETB TR1 //开启定时器1
RET
//定时器0
TIME0: PUSH ACC
PUSH PSW
MOV TH0,#0F8H
MOV TL0,#30H
ACALL DISP
POP PSW
POP ACC
RETI
//定时器1,用于产生基本时间--->秒
TIME1: PUSH ACC
PUSH PSW
MOV TH1,#3CH
MOV TL1,#0B0H
INC T_COUNT
MOV A,T_COUNT
CJNE A,#20,T_RETI
MOV T_COUNT,#0
INC SEC
MOV A,SEC
CJNE A,#60,T_RETI
MOV SEC,#0
INC MIN
MOV A,MIN
CJNE A,#60,T_RETI
MOV MIN,#0
INC HOUR
MOV A,HOUR
CJNE A,#24,T_RETI
MOV HOUR,#0
MOV MIN,#0
MOV SEC,#0
T_RETI: POP PSW /* MISTAKE */
POP ACC
RETI
//按键处理程序 (调整时间)
KEY_PROC: CLR TR1
PROC_KEY2: JB K2,PROC_KEY3
ACALL DELAY_10MS
JB K2,PROC_KEY3
JNB K2,$
ACALL LIGHT
INC MIN
MOV SEC,#0
MOV A,MIN
CJNE A,#60,PROC_CONV
MOV MIN,#0
PROC_CONV: ACALL CONV
PROC_KEY3: JB K3,PROC_KEY4
ACALL DELAY_10MS
JB K3,PROC_KEY2
JNB K3,$
ACALL LIGHT
INC HOUR
MOV SEC,#0
MOV A,HOUR
CJNE A,#24,PROC_CONV1
MOV HOUR,#0
PROC_CONV1: ACALL CONV
PROC_KEY4: JB K4,PROC_KEY2
ACALL DELAY_10MS
JB K4,PROC_KEY2
JNB K4,$
ACALL LIGHT
SETB TR1
PROC_RET: RET
//按键指示灯子程序
LIGHT: CLR LED
ACALL DELAY_10MS
SETB LED
ACALL DELAY_10MS
RET /* 从这里删除掉了R6,R7,后可使用*/
//定时响铃+铃声子程序 (响铃和定时时间查询合为一体)
TIMEING: MOV A,TIMED_HOUR
CJNE A,HOUR,TIMEING_RET
MOV A,TIMED_MIN
CJNE A,MIN,TIMEING_RET
MOV A,TIMED_SEC
CJNE A,SEC,TIMEING_RET
LOOP_BELL: CLR BELL
ACALL DELAY_1MS
SETB BELL
ACALL DELAY_1MS
MOV A,TIMED_MIN
CJNE A,MIN,TIMEING_RET
ACALL CONV
JB K4,LOOP_BELL
ACALL DELAY_10MS
JB K4,LOOP_BELL
JNB K4,$
CPL BELL_FLAG //闹铃是为0,现在取反则为1,停止定时扫描,闹铃取消掉
SETB LED //省去这条语句,就会使响铃停止,闹铃不关闭 (将LED小灯恢复到初始状态)
//加上这条语句,就会使响铃停止,闹铃被关闭(节省一点CPU资源)
TIMEING_RET:RET
//定时时间设置程序(设置报警时间)即时间调整
BELL_SET: ACALL BELL_CONV
BELL_KEY1: JB K1,BELL_KEY3
ACALL DELAY_10MS
JB K1,BELL_KEY3
JNB K1,$
INC TIMED_HOUR
MOV A,TIMED_HOUR
CJNE A,#24,SET_CONV
MOV TIMED_HOUR,#0
SET_CONV: ACALL BELL_CONV //调用定时设置转换程序
AJMP BELL_KEY1
BELL_KEY3: JB K3,BELL_KEY4
ACALL DELAY_10MS
JB K3,BELL_KEY1
JNB K3,$
INC TIMED_MIN
MOV A,TIMED_MIN
CJNE A,#60,SET_CONV1
MOV TIMED_MIN,#0
SET_CONV1: ACALL BELL_CONV //调用定时设置转换程序
AJMP BELL_KEY1
BELL_KEY4: JB K4,BELL_KEY1
ACALL DELAY_10MS
JB K4,BELL_KEY1
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
ACALL DELAY_100MS
ACALL LIGHT
JNB K4,$
RET
//定时时间 转换程序
BELL_CONV: MOV A,TIMED_HOUR
MOV B,#10
DIV AB
MOV SMG_SUF,A //定时时钟--->小时十位
MOV A,B
MOV SMG_SUF+1,A //定时时钟--->小时个位
MOV A,TIMED_MIN
MOV B,#10
DIV AB
MOV SMG_SUF+3,A
MOV A,B
MOV SMG_SUF+4,A
MOV A,TIMED_SEC
MOV B,#10
DIV AB
MOV SMG_SUF+6,A
MOV A,B
MOV SMG_SUF+7,A
RET
//1MS延时程序
DELAY_1MS: MOV R5,#5
LOOP2_1MS: MOV R6,#100
LOOP1_1MS: NOP
DJNZ R6,LOOP1_1MS
DJNZ R5,LOOP2_1MS
RET
//10MS延时程序
DELAY_10MS: MOV R2,#40
LOOP2: MOV R3,#250
LOOP1: NOP
DJNZ R3,LOOP1
DJNZ R2,LOOP2
RET
//100MS延时程序
DELAY_100MS:MOV R4,#10
LOOP3: ACALL DELAY_10MS
DJNZ R4,LOOP3
RET
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H //0,1,2,3,4,5,6,7,8,9,-
END