全套资料在压缩包里
;********************************
;单片机电子钟汇编程序
;MCU:AT89C2051 晶振:12M
;编写:舒新生 日期:2007.11.08
;手机:13073399262 QQ:625608148
;********************************
MIAO BIT P1.2;秒点位
HOU_S BIT P3.0 ;时十位
HOU_G BIT P3.1 ;时个位
MIN_S BIT P3.2 ;分十位
MIN_G BIT P3.3 ;分个位
H_KEY BIT P3.4 ;时调整键
M_KEY BIT P3.5 ;分调整键
SHAN BIT 0 ;秒点闪烁
LEDBUS EQU P1 ;显示数据总线
SECOND EQU 30H ;秒寄存器
MINUTE EQU 31H ;分寄存器
HOUR EQU 32H ;时寄存器
TIM_1 EQU 33H ;定时器0中断次数
TIM_2 EQU 34H ;定时器0中断次数
;********************************
ORG 0000H ;程序开始
LJMP INIT
ORG 000BH ;定时器0中断入口地址
LJMP TIMER0
ORG 0030H ;程序从30H开始
;********************************
; 单片机初始化
INIT: MOV SECOND, #0 ;秒置0
MOV MINUTE, #0 ;分置0
MOV HOUR, #0 ;开机后显示0点
MOV TIM_1, #10 ;中断10次为0.5秒
MOV TIM_2, #2 ;0.5*2=1秒
MOV SP, #60H ;堆栈指针指向60H
MOV TMOD, #01H ;定时器0为模式1(16位)
MOV TH0, #03CH
MOV TL0, #0B0H ;50毫秒初值(晶振12M)
SETB ET0 ;定时器0中断允许
SETB TR0 ;启动定时器0
SETB EA ;开总中断
;********************************
; 主程序
MAIN: JNB H_KEY, HT ;时调整键按下转到HT
JNB M_KEY, MT ;分调整键按下转到MT
ACALL DISP ;调用显示子程序
AJMP MAIN ;转LOOP继续检测按键状态
;********************************
; 时间调整
;----- 分调整 -----------------
MT: ACALL DISP ;调用显示子程序
JNB M_KEY, MT ;判断按键是否松开
INC MINUTE ;分加一
MOV A, MINUTE
CJNE A,#60, MAIN ;判断分是否加到60
MOV MINUTE, #0 ;分到60变为0
MOV SECOND, #0 ;秒置0
AJMP MAIN
;----- 时调整 -----------------
HT: ACALL DISP ;调用显示子程序
JNB H_KEY, HT ;判断按键是否松开
INC HOUR ;时加1
MOV A, HOUR
CJNE A,#24, MAIN
MOV HOUR, #0 ;判断时是否到24,时到24变0
AJMP MAIN
;********************************
; 显示子程序
DISP: MOV DPTR, #LEDTAB ;数码管段码表首地址送DPTR
MOV A, MINUTE ;分放入ACC
MOV B, #10 ;B放入10
DIV AB ;A/B,商在A余数在B
MOVC A, @A+DPTR ;查表取分十位段码
MOV LEDBUS, A ;段码送LEDBUS口显示
MOV C, SHAN
MOV MIAO, C ;秒点闪烁
CLR MIN_S ;打开分十位显示
ACALL D1MS ;延时1毫秒
SETB MIN_S ;关闭分十位显示
MOV A, B
MOVC A, @A+DPTR ;查表取分个位段码
MOV LEDBUS, A
MOV C, SHAN
MOV MIAO, C ;秒点闪烁
CLR MIN_G ;打开分个位显示
ACALL D1MS ;延时1毫秒
SETB MIN_G ;关闭分十位显示
MOV A, HOUR
MOV B, #10
DIV AB ;拆分小时的十位和个位
JZ DISP0 ;十位为0不显示十位
MOVC A, @A+DPTR
MOV LEDBUS, A
CLR HOU_S ;打开时十位显示
DISP0: ACALL D1MS
SETB HOU_S ;关闭时十位显示
MOV A, B
MOVC A, @A+DPTR
MOV LEDBUS, A
CLR HOU_G ;打开时个位显示
ACALL D1MS
SETB HOU_G ;关闭时个位显示
RET
;********************************
; 定时器0中断服务程序
TIMER0: MOV A, #0B1H ;定时器0中断服务子程序
ADD A, TL0 ;同步修正(参考本人的<如何是自制的单片机电子钟走时精准>)
MOV TL0, A
MOV TH0, #03CH ;重装定时器0初值
PUSH ACC ;入栈保护ACC和PSW
PUSH PSW
DJNZ TIM_1, RETI_1
MOV TIM_1, #10 ;中断10次为0.5秒
CPL SHAN ;取反闪烁位
DJNZ TIM_2, RETI_1
MOV TIM_2, #2 ;1秒时间到
INC SECOND ;秒加1
MOV A, SECOND
CJNE A,#60, RETI_1
MOV SECOND, #0 ;秒到60变0
INC MINUTE ;分加1
MOV A, MINUTE
CJNE A,#60, RETI_1
MOV MINUTE, #0 ;分到60变0
INC HOUR ;时加1
MOV A, HOUR
CJNE A,#24, RETI_1
MOV HOUR, #0 ;时到24变0
RETI_1: POP PSW ;出栈
POP ACC
RETI
;********************************
; 延时子程序
D1MS: MOV R7, #2 ;延时1毫秒子程序
D_1: MOV R6, #250 ;延时时间估算250*2*2=1000微秒=1毫秒
DJNZ R6, $
DJNZ R7, D_1
RET
;********************************
; 数码管段码表
LEDTAB: DB 14H,0D7H,4CH,45H,87H
; 0 1 2 3 4
DB 25H,024H,57H,04H,05H
; 5 6 7 8 9
END