《单片机及接口技术》设计性实验课题
注:文章仅供参考,请学弟学妹们自主完成课程设计,还有记得关注我哈!
学 院
专 业
学生姓名
学生学号
指导教师
课程学分
验收日期
教 师 评 语 | 教师签名: 日期: |
成 绩 评 定 | |
备 注 |
电子日历时钟 (for term exam)
目录
一.实验目的:
课程标志性内容的设计理解和综合运用,鼓励独立性设计和功能扩展的创新实践。
二.功能要求:
2.1基本性要求
通过按键切换完成以下功能:
- 显示北京时间;
- 能够校准时间;
- 使用汇编语言;
- 时、分、秒之间或年、月、日间以小数点分隔;
2.2发挥性要求
- 显示公历日期
- 能够校准日期
- 运动秒表
- 闹钟功能
- PC联机校准时间等
三.方案考虑:
3.1硬件方案
(1)采用4位LED数码管显示日期或者时间。
(2)显示器的驱动可采用“静态显示驱动”;也可采用“动态扫描驱动”,但后者比前者所需驱动电流要大。
(3)键盘的按键数目较多时则采用行列式矩阵结构为好。“一键多用”的构思和设计能大为减少按键的数目;要注意实际的应用中,时钟的按键不宜多;
(4)整体设计上应考虑其结构简单﹑操作简便﹑布局美观﹑成本低廉。
(5)可以考虑使用小数点或其他提示标志表示闹钟设置状态;
3.2软件方案
- “时钟”基准时间由单片机内部的定时中断提供,定时时间应是“秒”的整除数,且长短适宜。最长不能超过16位定时器的最长定时时间;最短不能少于中断服务程序的执行时间。通常来说基准时间越短,越有利于提高时钟的运行精确度。
- 用一个计数器对定时中断的次数进行计数,可实现“秒”定时,同理可以进行“分”﹑“时”定时,以及“日”﹑“月”﹑“年”定时。
- LED 数码管显示器采用“动态扫描驱动”时要注意的是:驱动信号的维持时间必须大于“起辉时间”(电流大起辉时间短),而驱动信号的间歇时间必须小于“余辉时间”(电流大余辉时间长),但驱动电流大小受硬件电路能力和LED数码管极限功耗的制约。
- 动态扫描显示方式在更新显示内容时,因LED数码管余辉的存在可能会造成显示字符的模糊,新内容写入显示器之前须将所有的LED数码管熄灭。
- 关于自动识别“月大﹑月小”和“平年﹑润年”问题的考虑
- 月大和月小
2月另外计算;
4月﹑6月﹑9月﹑11 月为月小30天,其余为月大31天。
- 平年和润年(普通年能整除4且不能整除100的为闰年,能整除400的是闰年)
平年的2月为28天;
润年的2月为29天。
四.实际方案:
4.1.实现的功能(操作指引)
a)时钟显示:
接通电源后,能够按照设定的初始时间进行走时,并用七段数码管显示。时、分、秒之间以小数点分隔
b)时钟校准:
c)日历显示
日历以“XXXX.XX.XX”的形式显示,如“2023.07.14”,年、月、日以小数点相隔。
能够实现秒-分-时-日-月-年的进位。能自动识别不同的月份和闰年、平年,采取不同的“天->月”的进位模式。
d)日历校准
4.2.硬件方案
a)采用4位7段LED数码管显示日期或者时间。显示器的驱动采用“动态扫描驱动”,各位数码管以极高的频率分时点亮,依靠人体视觉的暂留效果,实现了多位同时显示。
(4位7段数码管原理图,数码管*2)
数字编码表:
显示: 0 1 2 3 4 5 6 7 8 9
不带小数点: 3FH, 06H,5BH, 4FH, 66H, 6DH, 7DH, 07H,7FH, 6FH
带小数点: 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH
LED8:1DH LED7:1BH LED6:14H LED5:12H
LED4:0DH LED3:0BH LED2:04H LED1:02H
b)采用含有4个按键的独立键盘模块。通过按键的复用,使得单一按键可以用于多个功能,减少了的按键的使用数量。
(独立按键模块)
二进制码:
K1 0FDH
K2 0FEH
K3 0FBH
K4 0F7H
4.3.软件方案
a)时钟中断T0:
定时器T0有4种工作模式,通过定时器模式对模式控制寄存器TMOD进行选择。TMOD是一个8位的特殊功能寄存器,由低两位(D0,D1)决定工作模式。当D1D0=01时,定时器工作模式设置为方式1,即16位定时器。
选择定时器工作方式1,可得如下公式:
其中,T为定时时间,Tcy为机器周期,其值由晶振频率决定, 与fosc 成倒数关系,X的值由两个8位计数寄存器TH0,、TL0决定,在这里,我们让T的值为50ms。TH0、TL0的计算:开发板晶振频率为12MHz,设定时间间隔为50ms,则经过计算可以得到:TH0 = #3CH,TL0 = #0B0H.
“时钟”基准时间由单片机内部的定时中断提供,定时时间是“秒”的1/20,即50ms。用一个计数“DEDA”对定时中断的次数进行计数,可实现“秒”定时。DEDA计数20次即秒+1,然后DEDA清零。再以秒计数分,以分计数时,依次类推。
在中断程序钟,还需要作各个方面的判断。例如,若当前是第59秒,再加一秒则需退回0秒,同时分钟加一。同样道理,需要判断的还有时、月、年的进位,是否为闰年等等。
b) LED 数码管动态显示
将所有的数码管的段选线并接在一起,用IO接口控制,8个数码管轮流显示相应的信息,一遍显示完毕,隔一段时间,又这样循环显示。从计算机角度,每个数码管隔一段时间才显示一次,但是由于人的视觉暂留效应,只要隔离时间足够短,循环的周期足够长,每秒达到24次以上,看起来数码管就一直稳定显示了,这就是动态显示原理。
动态显示时候需要注意闪烁的频率。如果每秒显示的次数少,频率低,则显示的信息是闪烁的,这时候应该增加显示频率。如果每个数码管在每秒钟显示的总时间太短,则显示的亮度低,显示的信息不清楚,这时候应该增加显示的时间。通过DELAY函数,在每一位显示时适当加延时,每一位显示时加延时会使显示一遍的时间变长,就能够改变显示的频率。通过实验慢慢调试DELAY函数的参数,就能找到合适的闪烁频率。
c)按键的软件消抖
采用了延时函数按键消抖。
检测出键闭合后执行一个延时程序,这个延时较短,由DELAY函数提供。让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。
当检测到按键释放后,也要给延时,这个延时相对要长一点,由LDELAY或LLDELAY函数提供,待后沿抖动消失后才能转入该键的处理程序。
上述的DELAY、LDELAY、LLDELAY函数为设置了不同循环次数的自定义函数,能够实现不同长度的延时。
五.程序算法的流程图
(图一:主程序功能切换流程图)
(图二:平、闰年判断流程图)
(图三:键盘扫描子程序流程图)
(图四:调整时间流程图)
注:调整日期的原理与之相同。
六. 结果分析
将程序烧进单片机中进行测试,打开电源开关后,自动显示已设置的初始时、分、秒,并稳定走时。按下按键K4后可以转为日期显示,再按K4可以返回。另外,通过按下按键K1可以分别实现日期设置、时间设置。进入日期设置和时间设置后,通过K1,K2,K3按键即可进行校准,并且按K4即可随时返回时间/日期显示。将年份设定为2000年、1900年、2024年、2023年等不同年份,各个月份(尤其是2月)的最大天数均符合预期。在按键过程中,偶尔有误触和连触的情况,说明软件消抖可能有不完善的地方,也有可能是开发板硬件电路的瞬间电流的影响。
(展示图1:显示时间)
(展示图2:显示日期)
七.课程设计总结
自己拿GPT写就好了哈哈
八.源程序
ORG 0000H
AJMP BEGIN ;主程序入口
ORG 000BH
LJMP TINTO ;定时器0中断入口
ORG 0030H
HOUR EQU 0031H ;时存放地址
MIN EQU 0032H ;分存放地址
SEC EQU 0033H ;秒存放地址
DEDA EQU 0036H ;计数器
DAY EQU 0037H ;日存放地址
MON EQU 0038H ;月存放地址
YEARL EQU 0039H ;00xx年存放地址
YEARH EQU 0040H ;xx00年
DAYAM EQU 0041H ;一个月多少天存放地址
BEGIN:
CALL INITIAL ;系统初始化
LOOP1:
CALL SHOW_TIME1 ;显示时间
CALL SCAN_KEY ;扫描键盘
CJNE A,#0FDH,NOKEY ;若摁下0FDH键则调节时间
CALL LLDELAY
CALL ADJUST
JMP LOOP1
NOKEY:
CJNE A,#0F7H,LOOP1 ;回到循环开头
CALL LLDELAY
LOOP2:
CALL SHOW_DATE ;显示日期
CALL SCAN_KEY ;扫描键盘
CJNE A,#0FDH,DNOKEY ;若摁下0FDH键则调节日期
CALL LLDELAY
CALL DADJUST
DNOKEY:
CJNE A,#0F7H,LOOP2 ;若摁下F7H键则返回时间
CALL LLDELAY
JMP LOOP1
;显示时、分、秒
SHOW_TIME1:
MOV DPTR,#TABLE ;数字编码首地址
MOV A,HOUR ;显示时高位
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#14H ;led6
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2 ;.数字编码首地址
MOV A,B ;显示时低位
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#12H ;led5
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE
MOV A,MIN ;显示分高位
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0DH ;点亮led4
CALL SHOW
CALL DELAY ;显示持续一段
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0BH ;1
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE
MOV A,SEC ;显示秒
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#04H ;2
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#02H ;1
CALL SHOW
CALL DELAY
MOV P2,#00H
RET
SHOW_DATE:
MOV DPTR,#TABLE ;数字编码首地址
MOV A,YEARH ;显示年高位
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#1DH ;led6
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE ;.数字编码首地址
MOV A,B ;显示年低位
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#1BH ;led5
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE ;数字编码首地址
MOV A,YEARL ;显示年高位
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#14H ;led6
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2 ;.数字编码首地址
MOV A,B ;显示年低位
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#12H ;led5
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE
MOV A,MON ;显示月
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0DH ;点亮led4
CALL SHOW
CALL DELAY ;显示持续一段
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0BH ;LED3
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE ;显示日
MOV A,DAY
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#04H ;LED2
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#02H ;LED1
CALL SHOW
CALL DELAY
MOV P2,#00H
RET
;调节时
ADJUST:
CALL LDELAY
TIME1:
MOV DPTR,#TABLE ;显示时
MOV A,HOUR
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#14H ;led6
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#12H ;led5
CALL SHOW
CALL DELAY
MOV R4,#15
LOKEY2:
CALL SCAN_KEY
DJNZ R4,LOKEY2
CJNE A,#00H,CHECTK0 ;若未摁键则回到开头
AJMP TIME1
CHECTK0:
CJNE A,#0FEH,CHECKT1 ;若摁下0FEH键则时位加一
MOV A,HOUR
CJNE A,#23,INCT1
MOV HOUR ,#0
CALL LDELAY
AJMP TIME1
INCT1: INC A
MOV HOUR,A
CALL LDELAY
AJMP TIME1
CHECKT1:CJNE A,#0FBH,CHECKT2 ;若摁下0FBH键则时位减一
MOV A,HOUR
CJNE A,#0,DECT1
MOV HOUR,#23
CALL LDELAY
AJMP TIME1
DECT1: DEC A
MOV HOUR,A
CALL LDELAY
AJMP TIME1
CHECKT2:
CJNE A,#0F7H,ADJUST1 ;若摁下0F7H键返回,若按下的是0FDH则调MIN
CALL LDELAY
CHECKTR:
RET
;调节分
ADJUST1:
CALL LLDELAY
TIME2:
MOV DPTR,#TABLE
MOV A,MIN
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0DH
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0BH
CALL SHOW
CALL DELAY
MOV R4,#10
LOKEY3:
CALL SCAN_KEY
DJNZ R4,LOKEY3
CJNE A,#00H,CHECKT3 ;若未摁键则回到开头
AJMP TIME2
CHECKT3:CJNE A,#0FEH,CHECKT4 ;若摁下0FEH键则分位加一
MOV A,MIN
CJNE A,#59,INCT2
MOV MIN,#0
CALL LDELAY
LJMP TIME2
INCT2: INC A
MOV MIN,A
CALL LDELAY
LJMP TIME2
CHECKT4:CJNE A,#0FBH,CHECKT5 ;若摁下0FEH键则分位减一
MOV A,MIN
CJNE A,#0,DECT2
MOV MIN,#59
CALL LDELAY
LJMP TIME2
DECT2: DEC A
MOV MIN,A
CALL LDELAY
LJMP TIME2
CHECKT5:
CJNE A,#0F7H,ADJUST2 ;若摁下0F7H键返回,若按下的是0FDH则调SEC
CALL LDELAY
CHECKTR1:
RET
;调节秒
ADJUST2:
CALL LDELAY
TIME3:
MOV DPTR,#TABLE
MOV A,SEC
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#04H
CALL SHOW
CALL DELAY
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#02H
CALL SHOW
CALL DELAY
MOV R4,#10
LOKEY4:
CALL SCAN_KEY
DJNZ R4,LOKEY4
CJNE A,#00H,CHECKT6 ;若未摁键则回到开头
AJMP TIME3
CHECKT6:CJNE A,#0FEH,CHECKT7 ;若摁下0FEH键则分位加一
MOV A,SEC
CJNE A,#59,INCT3
MOV SEC,#0
CALL LDELAY
LJMP TIME3
INCT3: INC A
MOV SEC,A
CALL LDELAY
LJMP TIME3
CHECKT7:CJNE A,#0FBH,CHECKT8 ;若摁下0FBH键则分位减一
MOV A,SEC
CJNE A,#0,DECT3
MOV SEC,#59
CALL LDELAY
LJMP TIME3
DECT3: DEC A
MOV SEC,A
CALL LDELAY
LJMP TIME3
CJNE A,#0F7H,RETURN ;若摁下0F7H键返回,若按下的是0FDH则调HOUR
CALL LLDELAY
CHECKT8:RET ;返回
RETURN:
CALL ADJUST
;调节日历
DADJUST:
CALL LDELAY
DTIME1:
MOV DPTR,#TABLE ;显示世纪
MOV A,YEARH
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#1DH ;led8
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#1BH ;led7
CALL SHOW
CALL DELAY
MOV R4,#10
DLOKEY2:
CALL SCAN_KEY
DJNZ R4,DLOKEY2
CJNE A,#00H,DCHECTK0 ;若未摁键则回到开头
AJMP DTIME1
DCHECTK0:
CJNE A,#0FEH,DCHECKT1 ;若摁下0FEH键则年位加100
MOV A,YEARH
CJNE A,#99,DINCT1
MOV YEARH,#0
CALL LDELAY
AJMP DTIME1
DINCT1: INC A
MOV YEARH,A
CALL LDELAY
AJMP DTIME1
DCHECKT1:CJNE A,#0FBH,DCHECKT2 ;若摁下0FBH键则年位减100
MOV A,YEARH
CJNE A,#0,DDECT1
MOV YEARH,#99
CALL LDELAY
AJMP DTIME1
DDECT1: DEC A
MOV YEARH,A
CALL LDELAY
AJMP DTIME1
DCHECKT2:
CJNE A,#0F7H,DADJUST1 ;若摁下0F7H键返回,若按下的是0FDH则调年分
CALL LDELAY
DCHECKTR:
RET
;调节年分(与上同理)
DADJUST1:
CALL LLDELAY
DTIME2:
MOV DPTR,#TABLE
MOV A,YEARL
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#14H
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#12H
CALL SHOW
CALL DELAY
MOV R4,#10
DLOKEY3:
CALL SCAN_KEY
DJNZ R4,DLOKEY3
CJNE A,#00H,DCHECKT3 ;若未摁键则回到开头
AJMP DTIME2
DCHECKT3:CJNE A,#0FEH,DCHECKT4 ;若摁下0FEH键则年加一
MOV A,YEARL
CJNE A,#99,DINCT2
MOV YEARL,#0
CALL LDELAY
LJMP DTIME2
DINCT2: INC A
MOV YEARL,A
CALL LDELAY
LJMP DTIME2
DCHECKT4:CJNE A,#0FBH,DCHECKT5 ;若摁下0FBH键则年减一
MOV A,YEARL
CJNE A,#0,DDECT2
MOV YEARL,#99
CALL LDELAY
LJMP DTIME2
DDECT2: DEC A
MOV YEARL,A
CALL LDELAY
LJMP DTIME2
DCHECKT5:
CJNE A,#0F7H,DADJUST2 ;若摁下0F7H键返回,若按下的是0FDH则调SEC
CALL LDELAY
DCHECKTR1:
RET
;调节月(与上同理)
DADJUST2:
CALL LDELAY
DTIME3:
MOV DPTR,#TABLE
MOV A,MON
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0DH
CALL SHOW
CALL DELAY
MOV DPTR,#TABLE2
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#0BH
CALL SHOW
CALL DELAY
MOV R4,#10
DLOKEY4:
CALL SCAN_KEY
DJNZ R4,DLOKEY4
CJNE A,#00H,DCHECKT6 ;若未摁键则回到开头
AJMP DTIME3
DCHECKT6:CJNE A,#0FEH,DCHECKT7 ;若摁下0FEH键则月加一
MOV A,MON
CJNE A,#12,DINCT3
MOV MON,#1
CALL LDELAY
LJMP DTIME3
DINCT3: INC A
MOV MON,A
CALL LDELAY
LJMP DTIME3
DCHECKT7:CJNE A,#0FBH,DCHECKT8 ;若摁下FBH键则月减一
MOV A,MON
CJNE A,#1,DDECT3
MOV MON,#12
CALL LDELAY
LJMP DTIME3
DDECT3: DEC A
MOV MON,A
CALL LDELAY
LJMP DTIME3
DCHECKT8:
CJNE A,#0F7H,DADJUST3 ;若摁下0F7H键返回
CALL LDELAY
RET
;调节日(与上同理)
DADJUST3:
CALL LDELAY
DTIME4:
MOV DPTR,#TABLE
MOV A,DAY
MOV B,#10
DIV AB
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#04H
CALL SHOW
CALL DELAY
MOV A,B
MOVC A,@A+DPTR
ANL P2,#00H
ORL P2,#02H
CALL SHOW
CALL DELAY
MOV R4,#10
DLOKEY5:
CALL SCAN_KEY
DJNZ R4,DLOKEY5
CJNE A,#00H,JUDGE ;若未摁键则回到开头
AJMP DTIME4
JUDGE:
MOV R5,DAYAM
CJNE R5,#31,DCHECKT9 ;不跳则31天
D31CHECKT9:
CJNE A,#0FEH,D31CHECKT10 ;若摁下FEH键则日加一
MOV A,DAY
CJNE A,#31,D31INCT4
MOV DAY,#1
CALL LDELAY
LJMP DTIME4
D31INCT4: INC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
D31CHECKT10:CJNE A,#0FBH,DCHECKT11 ;若摁下FBH键则日减一
MOV A,DAY
CJNE A,#1,D31DECT4
MOV DAY,#31
CALL LDELAY
LJMP DTIME4
D31DECT4: DEC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
DCHECKT9:
MOV R5,DAYAM
CJNE R5,#30,D29 ;不跳则30天
CJNE A,#0FEH,DCHECKT10 ;若摁下FEH键则日位加一
MOV A,DAY
CJNE A,#30,DINCT4
MOV DAY,#1
CALL LDELAY
LJMP DTIME4
DINCT4: INC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
DCHECKT10:CJNE A,#0FBH,DCHECKT11 ;若摁下FBH键则日位减一
MOV A,DAY
CJNE A,#1,DDECT4
MOV DAY,#30
CALL LDELAY
LJMP DTIME4
DDECT4: DEC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
D29:
CJNE A,#0FEH,D29CHECKT10 ;若摁下FEH键则日位加一
MOV A,DAY
CJNE A,DAYAM,D29INCT4
MOV DAY,#1
CALL LDELAY
LJMP DTIME4
D29INCT4: INC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
D29CHECKT10:CJNE A,#0FBH,DCHECKT11 ;若摁下FBH键则日位减一
MOV A,DAY
CJNE A,#1,D29DECT4
MOV DAY,DAYAM
CALL LDELAY
LJMP DTIME4
D29DECT4: DEC A
MOV DAY,A
CALL LDELAY
LJMP DTIME4
CJNE A,#0F7H,DRETURN ;若摁下F7H键返回,若按下的是FDH则调世纪
CALL LLDELAY
DCHECKT11:RET ;返回
DRETURN:
CALL DADJUST
;扫描键盘
SCAN_KEY:
MOV P3,#0FH;扫描行
MOV A,P3
CJNE A,#0FH,KEY1;判断是否有键摁下
MOV A,#00H
AJMP KEYOUT
KEY1:
CALL DELAY;短暂延时再次判断是否有键摁下
CALL DELAY
MOV P3,#0FH
MOV A,P3
CJNE A,#0FH,SCAN1 ;如果不是误触,则识别
MOV A,#00H
AJMP KEYOUT
SCAN1: MOV A,P3;读取摁下哪个键
SCAN2: MOV P3,#0F0H
MOV R6,P3
ORL A,R6
KEYOUT: RET
;数码管显示
SHOW:
MOV P0,A
RET
;初始化
INITIAL:
MOV HOUR,#23 ;时
MOV MIN,#59 ;分
MOV SEC,#45 ;秒
MOV DEDA,#00 ;COUNT
MOV DAY,#27 ;时
MOV MON,#2 ;分
MOV YEARL,#23 ;秒
MOV YEARH,#20 ;COUNT
MOV DAYAM,#30
;开中断T0,TS 关T1
SETB EA
SETB ES
SETB ET0
SETB TR0
CLR ET1
CLR EX0
CLR EX1
MOV TMOD,#21H
MOV TH0,#3CH ;定时器0预设值(50ms)
MOV TL0,#0B0H
MOV P2,#00H ;MMMMMMD
RET
;程序延时
DELAY:
MOV 05H,#10
DE0:
MOV 06H,#100
DE1:
DJNZ 06H,DE1
DJNZ 05H,DE0
RET
LDELAY:
MOV 07H,#50
LDE0:
MOV 05H,#30
LDE1:
MOV 06H,#20
LDE2:
DJNZ 06H,LDE2
DJNZ 05H,LDE1
DJNZ 07H,LDE0
RET
LLDELAY:
MOV 07H,#50
LLDE0:
MOV 05H,#50
LLDE1:
MOV 06H,#30
LLDE2:
DJNZ 06H,LLDE2
DJNZ 05H,LLDE1
DJNZ 07H,LLDE0
RET
AGAIN1:
LJMP AGAIN
;外部中断定时器0,计1s
TINTO:
INC DEDA ;循环20次定时1s
MOV A,DEDA
CJNE A,#20,AGAIN1
MOV DEDA,#0
;判断进位
SECOND:
MOV A,MON
CJNE A,#02,NOMON2
MOV A,YEARL
MOV B,#4
DIV AB
MOV A,B
CJNE A,#0,NRUN
MOV A,YEARL
CJNE A,#0,ISRUN
MOV A,YEARH
MOV B,#4
DIV AB
MOV A,B
CJNE A,#0,NRUN
ISRUN:
MOV DAYAM,#28
JMP SETDAY
NRUN:
MOV DAYAM,#29
JMP SETDAY
NOMON2:
SUBB A,#8
JB CY,BELOW8 ;CY=1则跳转,即A小于8
MOV A,MON
ANL A,#01H
CJNE A,#0,IS_D30 ;A为偶数则不跳,8 10 12 :31DAY; 9 11 :30DAY
MOV DAYAM,#31
SJMP SETDAY
IS_D30: MOV DAYAM,#30
SJMP SETDAY
BELOW8:
MOV A,MON
ANL A,#01H
CJNE A,#0,IS_LD31 ;A为偶数则不跳,4 6 :30DAY; 1 3 5 7:31DAY
MOV DAYAM,#30
SJMP SETDAY
IS_LD31: MOV DAYAM,#31
SETDAY:
INC SEC
MOV A,SEC
CJNE A,#60,AGAIN
MINUTE:
MOV SEC,#0
INC MIN
MOV A,MIN
CJNE A,#60,AGAIN
HOURS:
MOV MIN,#0
INC HOUR
MOV A,HOUR
CJNE A,#24,AGAIN
MOV HOUR,#0
DAYS:
INC DAY
MOV A,DAY
MOV R7,DAYAM
CJNE R7,#29,T3031 ;29天一个月
CJNE A,#30,AGAIN
JMP MONS
T3031:
CJNE R7,#30,T31 ;29天一个月
MOV A,DAY
CJNE A,#31,AGAIN
JMP MONS
T31:
MOV A,DAY
CJNE A,#32,AGAIN
MONS:
MOV DAY,#1
INC MON
MOV A,MON
CJNE A,#13,AGAIN
YEARLS:
MOV MON,#1
INC YEARL
MOV A,YEARL
CJNE A,#100,AGAIN
MOV YEARL,#0
YEARHS:
INC YEARH
MOV A,YEARH
CJNE A,#100,AGAIN
MOV YEARH,#0
AGAIN: ;重装定时器0预设值(50ms)
MOV TH0,#3CH
MOV TL0,#0B0H
SETB TR0
RETI
;数字编码表
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
TABLE2: DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH
END