用AT89S51(单片机)设计一个电子钟

用AT89S51(单片机)设计一个电子钟,第1张

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;20h1半点标示位
;20H2闹钟设置中标示,为了显示区别用
;20H3闹钟设置时间CHECK到,使能标志位
;20H5开/关闹钟设置中标示;
;20H6闹钟1开关标志位
;20H7闹钟2开关标志位
;psw5用来做显示开关标志位
;21,22,23,24这里设置第一个闹钟的时间
;25,26,27,28这里设置第二个闹钟的时间
;29H
;P0口输出数码管段码,
;P2口 输出位选信号
;
;70H存放P10--3按钮值,
;71H--78H存放当前系统定时时间;
;78H 77H 76H 75H 74H 73H 72H 71H
; 星期 小时 分钟 秒钟
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ts equ 24h ;这里设置`24小时周期制
trr equ #0bbh ;这个是温度,晶振等的时间补偿值,
org 0000h ;定时太慢此值调大,定时太快调小;
jmp main
;org 0bh ;定时器0中断入口矢量
;jmp bz
org 1bh ;定时器1中断入口矢量
jmp t1int
org 0100h ;主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main:clr p30; ;关继电器
mov sp,#30h
mov r3,#20
mov tmod,#10h
;mov tl0,#06h ;定时器1,方式1,定时 50 MS;
;mov th0,#06h
mov tl1,#0b0h
mov th1,#3ch
mov ie,#88h ;开定时器1中断
;mov 65h,#5
; mov 66h,#100
;mov 64h,#4
;clr psw5
clr p30
setb pt1 ;设置T1为高优先级中断
;setb tr1
clr tr1 ;开启T1中断
acall send ;71h--78h 清零;
acall send1 ;20h--29h 清零;
dd: acall daa ;进行十进制调整71H-79H
;acall compare ;第一闹钟
;acall compare1 ;第二闹钟 设置值
;acall sound
acall disp ;数码管显示,78H--71H分别对应着8个数码管显示
acall key_scanf ;按钮控制
acall time_adj ;时间调整
acall lasttime ;调用上一次的设置值为当前定时值
;acall alarm1_set ;设置定时开/关闹钟
ajmp dd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;调用上次值为设置时间
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lasttime:push acc
mov a,70h
jnb acc2,return1
clr p30; 紧急暂停按钮,按下后暂停,并把上次设定值恢复
clr tr1
mov 73h,21h
mov 74h,22h
wait7:acall disp
acall key_scanf
mov a,70h
jnb acc0,wait7
mov 71h,#0
mov 72h,#0
mov 79h,#0
mov tl1,trr
mov th1,#3ch
mov r3,#20
setb tr1
setb p30
return1:pop acc
ret
daa: push acc ;对当前系统时间进行十进制调整
mov 71h,79h
mov r1,#71h
cjne @r1,#10,s2
mov 71h,#0h
mov 79h,#0
inc 72h
mov r1,#72h
cjne @r1,#6,s2
mov 72h,#0h
dec 73h
mov r1,#73h
cjne @r1,#255,s2
dec 74h
mov 73h,#9
s1: pop acc
ret
s2: mov r1,#73h
cjne @r1,#0,s1
mov r1,#74h
cjne @r1,#0,s1
clr p30
clr tr1
sjmp s1
h_half: ;半点CHECK
mov r1,#73h
mov a,74h
swap a
xchd a,@r1
cjne a,#29h,o25 ;CHECK 当前时间是否为29分钟
xchd a,@r1
mov r1,#71h
mov a,72h
swap a
xchd a,@r1
cjne a,#59h,o25 ;CHECK 当前时间为59秒
setb tr0 ;启动T0
setb 20h1 ;enable 半点flag bit
o25: xchd a,@r1
ret
compare: ;闹钟1设置时间与当前时间比较
push acc
jnb 20h6,nequ ;闹钟1开/关标志位
mov a,73h
cjne a,21h,nequ ;分低位
mov a,74h
cjne a,22h,nequ ;分高位
mov a,75h
cjne a,23h,nequ ;小时低位
mov a,76h
cjne a,24h,nequ ;小时高位
setb 20h3 ;到闹钟设置时间,使能闹钟报警标志位
nequ:pop acc
ret
compare1: ;闹钟2设置时间与当前时间比较
push acc
jnb 20h7,nequ33 ;闹钟2开/关标志位
mov a,73h
cjne a,25h,nequ33
mov a,74h
cjne a,26h,nequ33
mov a,75h
cjne a,27h,nequ33
mov a,76h
cjne a,28h,nequ33
setb 20h3 ;到闹钟设置时间,使能闹钟报警标志位
nequ33:
pop acc
ret
sound:
acall h_half ;check 是否半点
jb 20h1,s23 ;半点则返回
jb 20h0,s23
mov r1,#73h
mov a,74h
swap a
xchd a,@r1
cjne a,#59h,s25
xchd a,@r1
mov r1,#71h
mov a,72h
swap a
xchd a,@r1
s20: cjne a,#56h,s21
ajmp s26
s21: cjne a,#58h,s22
ajmp s26
s22: cjne a,#59h,s25
setb tr0
ajmp s26
s25: xchd a,@r1
s23: ret
s26: jb 20h0,s25
setb tr0
xchd a,@r1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中断服务程序,报时铃音信号输出
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bz: djnz 64h,rrr
jb 20h3,alarmsign;闹钟到点报时有效
jb 20h1,next ;半点报时
mov 64h,#4 ;05KHZ
ajmp justh
alarmsign:
mov 64h,#1; 2KHZ信号
justh:
djnz 66h,ccc
mov 66h,#100
djnz 65h,ccc ;产生1000次中断后关中断
mov 65h,#5 ;响05秒
setb 20h0
clr tr0
reti
next:mov 64h,#2 ;1KHZ信号,半点报时音
ccc: jb 20h3,cc
cpl p14 ;半点报时输出声音信号
rrr: reti
cc: cpl p14 ;闹钟报时输出声音信号
reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T1中断服务程序,定时器主时钟;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
t1int:
clr ea
mov tl1,trr
mov th1,#3ch
djnz r3,sd ;2050MS=1S
mov r3,#20
;cpl p14
inc 79h
clr 20h0
clr 20h1 ;半点报时标志清零
jb 20h3,sdd ;闹钟CHECK有效与否
clr tr0 ;关T0
sd: setb ea
reti
sdd: setb tr0 ;开T0,即开闹铃声音
setb ea
reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;显示子函数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dispnum1:; 显示
ajmp disp_num
disp:
push acc
;jb 20h5,dispnum1;开/关闹钟设置中界面
;jb 20h2,alarmcheck;闹钟设置时间中界面
jb psw5,closedisp
mov r2,#01h;位选通信号输出到P2口
mov r5,#2; 显示的位数循环控制
mov r0,#73h;分别取出内存76H-71H
cjne r3,#10,dot1;在小时和分之间闪烁DOT point
dot1:jnc dsp1
orl 73h,#10h
;dot1:cjne r3,#11,dsp1
;anl 73h,#0efh
dsp1:mov a,r2
;cpl a
mov p2,a
mov a,@r0
dsp2:mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
mov a,r2
rl a
mov r2,a
inc r0
djnz r5,dsp1
anl 73h,#0efh
pop acc
ret
closedisp:; 关显示
acall delay
mov p0,#0ffh
mov p2,#0
pop acc
ret
;;;;;;;;;;;;;;;;;闹钟的定时设置显示
alarmcheck:
mov r2,#01h
mov r5,#2 ;两位显示22-21H对应定时设置值
mov r0,#21h
dsp21:
mov a,r2
;cpl a
mov p2,a
mov a,@r0
mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
mov a,r2
rl a
mov r2,a
inc r0
djnz r5,dsp21
pop acc
ret
bcd:; 共阳接法数码管段码表
db 0c0h,0f9h,0a4h,0b0h
db 99h,92h,82h,0f8h
db 80h,90h,88h,83h
db 0c6h,0a1h,86h,8eh; 不带小数点七段
db 40h,79h,24h,30h,19h
db 12h,02h,78h,00h,10h
db 0ffh,0bfh,7fh,3fh; 带小数点七段
delay:mov r6,#4h
tm: mov r4,#0h
ee: djnz r4,ee; 延时2048US=2MS
djnz r6,tm
ret
send:mov r7,#9; 初始化设置
mov r0,#71h
mov a,#0h
ss: mov @r0,a
inc r0
djnz r7,ss
mov 78h,#1h
mov 77h,#01ah
;mov 71h,#1
;mov 72h,#2
;mov 73h,#3
;mov 74h,#4
ret
send1:; 初始化
mov r7,#10
mov r0,#20h
mov a,#0
ss1: mov @r0,a
inc r0
djnz r7,ss1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;开/关闹钟界面显示
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
disp_num:
mov p2,#0f7h
mov a,29h ;当前要 *** 作的闹钟号码
mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
pop acc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
key_scanf:; 按钮处理
push acc
mov 70h,#0
orl p1,#0fh
mov a,p1
cpl a
anl a,#07h
jz nokey1
acall daa
acall disp
mov a,p1
cpl a
anl a,#07h
jz nokey1
mov 70h,a
key_wait:; 等按钮放下
acall daa
acall disp
mov a,p1
cpl a
anl a,#07h
jnz key_wait
mov a,70h
jnb acc1,nokey1
cpl psw5
nokey1:; 无按钮
pop acc
ret
a_on_off:
jnb 29h0,iii
cpl 20h6
iii: jnb 29h1,out_2
cpl 20h7
out_2:
ajmp alarmnum
alarmnum:
setb 20h5
acall daa
acall disp
acall key_scanf
clr 20h5
mov a,70h
jb acc0,a_on_off
jb acc1,alar_adj_1
jb acc2,a_num_inc
acall numb
ajmp alarmnum
alarm1_set:
push acc
mov a,70h
jb acc1,alarmnum
alarm1_out:
clr 20h2
pop acc
ret
a_num_inc:
inc 29h
mov a,29h
anl a,#0fh
cjne a,#3,alarmnum
anl 29h,#0
ajmp alarmnum
alar_adj_1:
setb 20h2
acall daa
orl 21h,#10h
acall disp
anl 21h,#0fh
acall key_scanf
mov a,70h
jb acc1,hadj_1
jb acc2,minc_1
ajmp alar_adj_1
madj_2:
acall daa
orl 25h,#10h
acall disp
anl 25h,#0fh
acall key_scanf
mov a,70h
jb acc1,hadj_2
jb acc2,minc_2
ajmp madj_2
hadj_1:
acall daa
orl 23h,#10h
acall disp
anl 23h,#0fh
acall key_scanf
mov a,70h
jb acc1,madj_2
jb acc2,hinc_1
ajmp hadj_1
hadj_2:acall daa
orl 27h,#10h
acall disp
anl 27h,#0fh
acall key_scanf
mov a,70h
jb acc1,alarm1_out
jb acc2,hinc_2
ajmp hadj_2
minc_1:
inc 21h
mov r1,#21h
cjne @r1,#10,alar_adj_1
mov 21h,#0
inc 22h
mov r1,#22h
cjne @r1,#6,alar_adj_1
mov 22h,#0h
ajmp alar_adj_1
minc_2:
inc 25h
mov r1,#25h
cjne @r1,#10,madj_2
mov 25h,#0
inc 26h
mov r1,#26h
cjne @r1,#6,madj_2
mov 26h,#0
ajmp madj_2
hinc_1:
inc 23h
mov r1,#23h
cjne @r1,#10,ss14
mov 23h,#0
inc 24h
ss14:
mov a,24h
swap a
xchd a,@r1
cjne a,#ts,ss15
mov 23h,#0
mov 24h,#0
ajmp hadj_1
ss15:xchd a,@r1
ajmp hadj_1
hinc_2:
inc 27h
mov r1,#27h
cjne @r1,#10,sss14
mov 27h,#0
inc 28h
sss14:
mov a,28h
swap a
xchd a, @r1
cjne a,#ts,sss15
mov 27h,#0
mov 28h,#0
ajmp hadj_2
sss15:
xchd a,@r1
ajmp hadj_2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;时间调整程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
time_adj:;
clr psw5
push acc
mov a,70h
jb acc0,l1;P10调时功能键,每按一次切换一位
ajmp nokeyout
adj_out:
mov 21h,73h
mov 22h,74h
setb p30 ;闭合继电器
setb tr1
nokeyout:
pop acc
ret
QQ: anl 73h,#0fh
anl 74h,#0fh
;anl 78h,#0fh
ret
l1: clr tr1;acall dab; 分钟调整
orl 73h,#10h;点亮分右下角的小数点,当前调整位置
acall disp
acall QQ
acall key_scanf
clr psw5
mov a,70h
jb acc0,h_adj;切换到小时调整
jb acc1,m_inc;P12加1按钮
ajmp l1
h_adj:; 小时调整
;acall dab
orl 74h,#10h
acall disp
acall QQ
acall key_scanf
clr psw5
mov a,70h
jb acc0,out_adj;切换到星期调整
jb acc1,h_inc;小时加1
ajmp h_adj
w_adj:
acall daa
orl 78h,#10h
acall disp
acall QQ
acall key_scanf
clr psw5
mov a,70h
jb acc0,out_adj
jb acc2,w_inc
ajmp w_adj
out_adj:
ajmp adj_out
m_inc:;;;;;;;;;;;;;;; 调整分时,对定时复位,初始化
clr tr1
mov 71h,#0
mov 72h,#0
mov 79h,#0
mov tl1,trr
mov th1,#3ch
mov r3,#20
inc 73h
mov r1,#73h
cjne @r1,#10,s12
mov 73h,#0
inc 74h
mov r1,#74h
cjne @r1,#10,s12
mov 74h,#0
s12: ajmp l1
;;;;;;;;;;;;;;;;;;;;;;调整小时位
h_inc:
inc 74h
mov r1,#74h
cjne @r1,#10,s14
mov 74h,#0
;inc 76h
s14: ajmp h_adj
;mov a,76h
;swap a
;xchd a,@r1
;cjne a,#ts,s15;;;12进制,24进制设置值决定
;mov 75h,#0
;mov 76h,#0
;ajmp h_adj
;s15: ;xchd a,@r1
;ajmp h_adj
;;;;;;;;;;;;;;;;;;;;;;;调整星期位
w_inc:
inc 78h
mov r1,#78h
cjne @r1,#8,s16
mov 78h,#1h
s16: ajmp w_adj
;;;;;;;;;;;;;;;;;;;;;;;当前闹钟开/关情况报告位
numb:clr 29h4
jnb 29h0,iii1
jnb 20h6,iii1
setb 29h4
iii1:jnb 29h1,out_21
jnb 20h7,out_21
setb 29h4
out_21:
jnb 20h6,out_12
jnb 20h7,out_13
mov 77h,#1dh
ajmp out_22
out_12:
jnb 20h7,out_14
mov 77h,#1bh
ajmp out_22
out_13:
mov 77h,#1ch
ajmp out_22
out_14:
mov 77h,#1ah
out_22:
ret
end

朋友以下是本人历时一个月殚精竭虑自主开发的一个8位51单片机时钟程序,望吾之兄弟姐妹习之,此程序乃采用一键控制,通过感知按下键持续时间的长短来进行调整时间,闹铃,6只共阳数码管输出显示,此外还包括整点铃声功能,在看程序之前我先交代一下运行该程序的硬件要求:12M晶振,P0端口驱动显示,P20到P25控制显示扫描,P27输出铃声,注意:铃声功放三极管应采用pnp管。以下是该程序:
ORG 00H
SETB TR0
JMP START
ORG 000BH
LJMP T0
START: MOV IE,#82H
MOV TMOD,#01H
MOV DPTR,#TAB
MOV SP,#60H
MOV 20H,#0
MOV R0,#0
MOV R1,#0
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
MOV 50H,#0
MOV 51H,#0
MOV 52H,#0
MOV 53H,#0
MOV 54H,#0
MOV 55H,#0
MOV A,TL0
ADD A,0B5H
MOV TL0,A
MOV TH0,#3CH
LOOP: ANL 20H,#08H
UNSV: MOV R1,#0
LCALL DISPLAY
JB 03H,LOP1
LCALL SOUND
LCALL HDLY
LOP1: MOV P3,#0FEH ;按键监视
MOV A,P3
CJNE A,#0FEH,LOP2
MOV R1,#0
JMP LOOP
LOP2: MOV R1,#2 ;误按判断
LOP3: LCALL HD
DJNZ R1,LOP3
JNB 04H,LOOP
CLR 04H
LOP4: INC R1
MOV C,00H ;调秒
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,LOP5
JMP LOOP
LOP5: JNB 05H,LOP4
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,TF
MOV R2,#0
MOV R3,#0
JMP LOP4
TF: CLR 04H
LOP6: INC R1
MOV C,01H ;调分
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,LOP7
JMP LOOP
LOP7: JNB 05H,LOP6
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,TS
INC R4
MOV R1,#0
CJNE R4,#10,LOP6
MOV R4,#0
INC R5
CJNE R5,#6,LOP6
MOV R5,#0
JMP LOP6
TS: CLR 04H
LOP8: INC R1
MOV C,02H ;调时
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,LOP9
JMP LOOP
LOP9: JNB 05H,LOP8
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,TN
INC R6
CJNE R7,#2,NO2
CJNE R6,#4,LOP8
MOV R7,#0
MOV R6,#0
NO2: CJNE R6,#10,LOP8
MOV R6,#0
INC R7
JMP LOP8
TN: CLR 04H ;调闹铃
SETB RS0
CLR RS1
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
NS: INC R1 ;闹铃秒调整
MOV C,00H
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,NS1
JMP NH2
NS1: JNB 05H,NS
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,NF
INC R2
CJNE R2,#10,NS
MOV R2,#0
INC R3
CJNE R3,#6,NS
MOV R3,#0
JMP NS
NF: CLR 04H ;闹铃分
NF1: INC R1
MOV C,01H
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,NF2
LJMP NH2
NF2: JNB 05H,NF1
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,NH
INC R4
CJNE R4,#10,NF1
MOV R4,#0
INC R5
CJNE R5,#6,NF1
MOV R5,#0
JMP NF1
NH: CLR 04H ;闹铃时调整
NH1: INC R1
MOV C,02H
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,NH3
NH2: MOV 50H,R2
MOV 51H,R3
MOV 52H,R4
MOV 53H,R5
MOV 54H,R6
MOV 55H,R7
CLR RS0
CLR RS1
LJMP LOOP
NH3: JNB 05H,NH1
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,NH2
INC R6
CJNE R7,#2,NOT2
CJNE R6,#4,NH1
MOV R6,#0
MOV R7,#0
JMP NH1
NOT2: CJNE R6,#10,NH1
MOV R6,#0
INC R7
JMP NH1
;子程序区
TIMES: CJNE R0,#20,LOOP16
MOV R0,#0
INC R2
CJNE R2,#10,LOOP16
MOV R2,#0
INC R3
CJNE R3,#6,LOOP16
MOV R3,#0
ADMINI: INC R4
CJNE R4,#10,LOOP16
MOV R4,#0
INC R5
CJNE R5,#6,LOOP16
MOV R5,#0
HOUR: INC R6
LCALL SOUND ;整点铃声
CJNE R7,#2,LOOP14
CJNE R6,#4,LOOP16
MOV R6,#0
MOV R7,#0
JMP LOOP16
LOOP14: CJNE R6,#10,LOOP16
MOV R6,#0
INC R7
LOOP16: RET
DISPLAY:MOV P2,#0FFH
MOV A,R2
MOVC A,@A+DPTR
MOV P0,A
MOV C,00H
MOV P20,C
MOV P2,#0FFH
MOV A,R3
MOVC A,@A+DPTR
MOV P0,A
MOV P21,C
MOV P2,#0FFH
MOV A,R4
MOVC A,@A+DPTR
MOV P0,A
MOV C,01H
MOV P22,C
MOV P2,#0FFH
MOV A,R5
MOVC A,@A+DPTR
MOV P0,A
MOV P23,C
MOV P2,#0FFH
MOV A,R6
MOVC A,@A+DPTR
MOV P0,A
MOV C,02H
MOV P24,C
MOV P2,#0FFH
MOV A,R7
MOVC A,@A+DPTR
MOV P0,A
MOV P25,C
MOV P2,#0FFH
RET
HDLY: MOV 40H,#2
HDL1: MOV 41H,#25
HDL2: MOV 42H,#100
HDL3: DJNZ 42H,HDL4
DJNZ 41H,HDL2
DJNZ 40H,HDL1
JMP HDOT
SOUT: SETB 05H
HDOT: RET
HDL4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,SOUT
CLR 05H
LCALL DISPLAY
JMP HDL3
HD: MOV 30H,#5
HD1: MOV 31H,#50
HD2: MOV 32H,#100
HD3: LCALL DISPLAY
DJNZ 32H,HD4
DJNZ 31H,HD2
DJNZ 30H,HD1
SETB 04H ;计满标志位
JMP HDOUT
HD4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
MOV 33H,#50
HD5: MOV 34H,#100
DJNZ 34H,$
DJNZ 33H,HD5
MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
CLR 04H
HDOUT: RET
SOUND: MOV 30H,#10
SO1: MOV 31H,#100
SO2: MOV 32H,#3
MOV C,P27
CPL C
MOV P27,C
SO3: MOV 33H,#25
DJNZ 33H,$
DJNZ 32H,SO3
DJNZ 31H,SO2
DJNZ 30H,SO1
RET
T0: PUSH PSW
PUSH ACC
CLR RS1
CLR RS0
MOV A,TL0
ADD A,#0B5H
MOV TL0,A
MOV TH0,#3CH
INC R0
LCALL TIMES
MOV A,R2
CJNE A,50H,TO
SETB 03H
MOV A,R3
CJNE A,51H,TO
MOV A,R7
CJNE A,55H,TO
MOV A,R6
CJNE A,54H,TO
MOV A,R5
CJNE A,53H,TO
MOV A,R4
CJNE A,52H,TO
MOV A,R2
ADD A,R3
ADD A,R4
ADD A,R5
ADD A,R6
ADD A,R7
JZ TO
CLR 03H
TO: POP ACC
POP PSW
RETI
TAB: DB 0C0H 0F9H 0A4H 0B0H 099H
DB 092H 082H 0F8H 080H 090H
END

#include <reg52h>
#include<stddefh>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_FLAG
#define LCD1602_PORT P0

sbit lcd1602_rs=P2^0;
sbit lcd1602_e=P2^2;
sbit lcd1602_rw=P2^1;
sbit lcd1602_busy=P0^7;
sbit key_ch=P3^5;
sbit key_add=P3^6;
sbit key_minus=P3^7;

uchar i,sec,min,h,date,month,flag;
uint year;
uchar chgstr[7]={"  ","sec","min","hour","date","min","year"};
uchar j,k,m,n,o,p;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar timestr[10],datestr[10];
void init();
void delay(uint);
void time_display();
void date_display();
void control();
void time();
/

函数名称:lcd1602_CheckBusy()
函数功能:状态查询

/

void lcd1602_CheckBusy()
{
do
{
lcd1602_busy=1;
lcd1602_rs=0;
lcd1602_rw=1;
lcd1602_e=0;
lcd1602_e=1;
}
while(lcd1602_busy);
}

/

函数名称: lcd1602_WriteCmd()
函数功能:写命令
入口参数:命令字
出口参数:无

/

void lcd1602_WriteCmd(const uchar cmd)
{
lcd1602_CheckBusy();
lcd1602_rs=0;
lcd1602_rw=0;
lcd1602_e=1;
LCD1602_PORT=cmd;
lcd1602_e=0;
}

/

函数名称:lcd1602_WriteData()
函数功能:写数据
入口参数:c--待写数据
出口参数:无

/

void lcd1602_WriteData(const uchar c)
{
lcd1602_CheckBusy();
lcd1602_rs=1;
lcd1602_rw=0;
lcd1602_e=1;
LCD1602_PORT=c;
lcd1602_e=0;
}

/

函数名称:lcd1602_Init()
函数功能:初始化LCD
入口参数:无
出口参数:无

/

void lcd1602_Init()
{
lcd1602_WriteCmd(0x38); //显示模式为8位2行57点阵
lcd1602_WriteCmd(0x0c); //display enable,flag enable,flash enable,
lcd1602_WriteCmd(0x06); //flag move to right,screen don't move
lcd1602_WriteCmd(0x01); //clear screen
}

/

函数名称:lcd1602_Display()
函数功能: 字符显示
入口参数:ptr--字符或字符串指针
出口参数:无
说    明:用户可通过以下方式来调用:
           1)lcd1602_Display("Hello,world!");
           2) INT8U 存储类型 txt[]="要显示的字符串";
              或者 INT8U 存储类型 txt[]={'t','x','t',,'\0'};
              INT8U ptr;
              ptr=&txt;
              lcd1602_Display(ptr);
              或 lcd1602_Display(txt);
              或 lcd1602_Display(&txt);

/

void lcd1602_Display(const uchar ptr,uchar line,uchar xaddr)
{
uchar data i=0;
uchar data q;

q=ptr;
switch(line)
{
case 0:
lcd1602_WriteCmd(0x80+xaddr);
while(q!=NULL && (q!='\0') && i<16)
{
lcd1602_WriteData(q);
q++;
i++;
}
break;
case 1:
lcd1602_WriteCmd(0xc0+xaddr);
while(q!=NULL && (q!='\0') && i<16)
{
lcd1602_WriteData(q);
q++;
i++;
}
break;
}
}


void main()
{
lcd1602_Init();
init();
while(1)
{
time_display();
date_display();
control();
}
}
void init()
{
i=0;
sec=0;
min=0;
h=12;
date=26;
month=6;
year=2017;
flag=0;
EA=1;
ET0=1;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void time_display()
{
timestr[7]=0x30+sec%10;
timestr[6]=0x30+sec/10;
timestr[5]=':';
timestr[4]=0x30+min%10;
timestr[3]=0x30+min/10;
timestr[2]=':';
timestr[1]=0x30+h%10;
timestr[0]=0x30+h/10;
timestr[8]=0;
lcd1602_Display(timestr,1,3);
}
void date_display()
{
datestr[9]=0x30+date%10;
datestr[8]=0x30+date/10;
datestr[7]=':';
datestr[6]=0x30+month%10;
datestr[5]=0x30+month/10;
datestr[4]=':';
datestr[3]=0x30+year%10;
datestr[2]=0x30+year/10%10;
datestr[1]=0x30+year/100%10;
datestr[0]=0x30+year/1000;
lcd1602_Display(datestr,0,2);
}
void control()
{
if(!key_ch)
{
delay(5);
if(!key_ch)
{
flag++;
TR0=0;
if(flag==7)
{flag=0;TR0=1;lcd1602_Init();}
lcd1602_Display(chgstr[flag],1,12);
}
}
while(!key_ch);
if(flag==1&&key_add==0)
{
while(!key_add);
sec++;
if(sec==60)
sec=0;
}
if(flag==1&&key_minus==0)
{
while(!key_minus);
sec--;
if(sec==-1)
sec=59;
}

if(flag==2&&key_add==0)
{
while(!key_add);
min++;
if(min==60)
min=0;
}
if(flag==2&&key_minus==0)
{
while(!key_minus);
min--;
if(min==-1)
min=59;
}

if(flag==3&&key_add==0)
{
while(!key_add);
h++;
if(h==24)
h=0;
}
if(flag==3&&key_minus==0)
{
while(!key_minus);
h--;
if(h==-1)
h=23;
}

if(flag==4&&key_add==0)
{
while(!key_add);
date++;
if(date==29)
if((year%4!=0)&&(month==2))
date=1;
if(date==30)
if((year%4==0)&&(month==2))
date=1;
if(date==31)
if((month==4)||(month==6)||(month==9)||(month==11))
date=1;
if(date==32)
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
date=1;
}

if(flag==4&&key_minus==0)
{
while(!key_minus);
if(date>1)date--;
}

if(flag==5&&key_add==0)
{
while(!key_add);
month++;
if(month==13)
month=1;
}
if(flag==5&&key_minus==0)
{
while(!key_minus);
month--;
if(month==0)
month=12;
}

if(flag==6&&key_add==0)
{
while(!key_add);
year++;
if(year==99)
year=1;
}
if(flag==6&&key_minus==0)
{
while(!key_minus);
year--;
if(year==0)
year=99;

}

void T0_rpt() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
i++;
time();
}

void time()
{
if(i==20)
{
i=0;
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
h++;
if(h==24)
{
h=0;
min=0;
sec=0;
date++;
if(date==29)
if((year%4!=0)&&(month==2))
{
date=1;
month++;
if(month==13)
{
month=1;
year++;
}
}
if(date==30)
if((year%4==0)&&(month==2))
{
date=1;
month++;
if(month==13)
{
month=1;
year++;
}
}
if(date==31)
if((month==4)||(month==6)||(month==9)||(month==11))
{
date=1;
month++;
if(month==13)
{
month=1;
year++;
}
}
if(date==32)
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
{
date=1;
month++;
if(month==13)
{
month=1;
year++;
}
}
}
}
}

}

#include<reg51h>
#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsigned char sec=0,min=0,hour=0,scanled;
unsigned char key,time; 
unsigned char disdat[6];
sbit K=P1^0;
void dischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
void t0isr() interrupt 1 //秒计时
{
TR0=0;
TH0=0x3c;
TL0=0xb0;
TR0=1;
time++;
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
dischg();
}
void t1isr() interrupt 3 //显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x02;
P0=~ledtab[disdat[4]]&0x7f;
break;
case 2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x08;
P0=~ledtab[disdat[2]]&0x7f;
break;
case 4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=0;
scanled=0;
time=0;
key=0;
dischg();
while(1)
{
if(K==0)
{
while(K==0);
key++;
key%=2;
}
switch(key)
{
case 0:
TR0=1;
break;
case 1:
TR0=0;
break;
}
}
}

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

额。。。。。这个东西就是零碎的东西加起来变成一个一个整体的啊,讲个思路,写个中断服务程序,里面的是led灯亮的程序,和1秒的计时程序,写个beep子程序控制蜂鸣器,写个display子程序,控制icl0809,主程序循环控制,显示数码管,显示am,过了12,进入中断,显示pm,这个其实很简单的,我才大三,单片机才学了四个星期,我都会做,相信你能行的。。。

89C51可以了,你最熟悉的,如果你用其他的也可以,不过你可能要从新学指令,麻烦!!
元器件:
4位数码管,4个三极管(用来控制LED),开关(你自己看要几个),在就是构成IC运行所需要的元器件
这些就够了,当然你如果还要闹钟的话,可以加个蜂鸣器,也用三极管驱动


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/13396951.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-28
下一篇 2023-07-28

发表评论

登录后才能评论

评论列表(0条)

保存