数码管电子时钟.docx
《数码管电子时钟.docx》由会员分享,可在线阅读,更多相关《数码管电子时钟.docx(40页珍藏版)》请在冰点文库上搜索。
数码管电子时钟
单片机大作业
——电子日历时钟的制作
班级:
姓名:
学号:
编号:
07
一、题目及功能要求
1.制作一个电子日历时钟,使用汇编语言进行软件编程
2.实现功能
(1)显示北京时间并能校准
(2)时、分、秒之间以及年、月、日之间以小数点隔开
(3)显示公历日期并能校准,能够自动识别“闰年”以及“大月、小月”
(4)运动秒表,能够后台计时,秒表精确到0.05S
(5)闹钟功能,有闹钟开关,并能显示当前闹钟是否开启
(6)整点报时提醒
二、硬件方案
1.AT89S52最小系统
2.显示电路采用动态扫描驱动电路,AT89S52的P0口连接74LS244总线驱动器,输出信号利用三极管8550进行放大,通过P1口对数码管进行段选扫描,AT89S52的P1.2~P1.7口对数码管进行位选扫描
3.两个按键开关,分别接AT89S52的两个外部中断引脚
4.AT89S52的P2.0口输出经三极管9012放大,驱动有源蜂鸣器发声
三、电路原理图
四、系统元件布局、布线图
五、元器件清单
型号及标称值
数量
AT89S52
1
HD74LS244
1
晶体管8550
6
晶体管9012
1
蜂鸣器(有源)
1
电解电容10uF
1
7段数码管(共阳)
6
3K电阻
9
200电阻
8
4.7K电阻
1
按钮开关
3
12M晶振
1
30pF瓷介电容
2
六、软件方案
1.“时钟”基准时间由AT89S52定时器0中断提供,设置为最高优先级,定时器0设为工作方式1,即16进制计数器方式,计数初值设为15536,即可实现0.05s中断一次,连续中断20次即可实现一秒定时。
2.由于使用较多数码管,显示模块使用动态扫描方式,定义全局变量,保存各个数位的BCD码,通过查表,将字模送到P0口进行输出;为了显示闹钟的状态,设置了另一字模数据表,在显示前进行判断,若为闹钟开关设置状态则调用此字模数据表。
3.按键中断的时候,在2个按键都没按下的状态,2个中断引脚都为低电平,则一直调用中断0的子程序,每次进入中断0子程序中便检测中断1的引脚是否为高电平,即检测开关KEY1是否按下;相反,在按下KEY0时,进入中断1子程序,每次进入中断1子程序都检测中断0的引脚是否为高电平,为高电平则表示已按下。
4.用寄存器R7来记录当前切换的功能,分别为,0-时间;1-日期;2-闹钟;3-闹钟开关;4-秒表。
5.秒表的实现,采用基准时钟作为秒表时钟源,精度可以达到0.05s。
6.闹钟的实现,在主程序中,循环判断闹钟设置的时分与当前时分是否相等,闹钟持续1分钟
7.整点报时的实现,在主程序中,先判断当前时间的秒,若为0再判断分,再为0则使蜂鸣器嘀一声,循环判断。
七、程序框图
1.主程序
2.定时器0中断子程序
3.外部中断0子程序
4.外部中断1子程序
八、系统使用说明
1.接通电源自动复位,读取初始状态,时钟--“00.00.00”,日期—“10.06.06”,闹钟—“06.00.00”,闹钟状态—“OFF”,秒表—“00.00.00”。
2.按键KEY1为“切换功能/调节”按钮,按键KEY0为“确定/计时开始/计时暂停/闹钟开关按钮
3.第一功能----电子时钟:
按KEY0键进入时校准状态,“时”数码管闪烁,此时按KEY1键可以调节小时,“时”调节范围为00~24,按KEY0可切换到“分”设置,调节范围为00~59再按KEY0可切换到“秒”设置,调节范围为00~59。
4.第二功能----电子日历:
在电子时钟功能下,按KEY1可以切换到电子日历功能。
进入电子日历功能,可以对“年”.“月”.“日”进行校准,校准方式同电子时钟的校准方式一样,自行摸索。
5.第三功能----闹钟设置:
在电子日历功能下,按KEY1可以切换到闹钟设置功能。
闹钟的设置同电子时钟的设置一样。
6.第四功能----闹钟开关:
在闹钟设置功能下,按KEY1可以切换到闹钟开关设置。
默认状态为关闭闹钟功能,显示“OFF”,按KEY0可以调节闹钟开关,打开闹钟功能则显示“ON”。
闹钟设置为“ON”时,最后一个数码管的小数点会亮起,可以在任何功能状态下提示闹钟功能已开启。
7.第五功能----秒表:
在闹钟设置功能下,按KEY1可以切换到秒表功能。
进入秒表功能,按KEY0开始计时,再按KEY0则暂停计时,在秒表计时的时候按KEY1可以切换到其他功能,而秒表则在后台计时,在秒表暂停时按KEY1可以将秒表清零。
九、体会
第一次使用AtmelDesignerWinter09布出一个完整的PCB制板图,并用覆铜板做成实物,最大的体会是:
软件能画出来的图,我们不一定就能把这样的电路板做出来。
布线时要考虑的因素除整体布局、飞线数目外,最重要的是线的宽度、线与线的间距、焊盘的大小。
唯有线宽合适、间距合理才能做出符合要求的电路板。
刚制成的电路板要先使用万用表检测各导线的连接情况,解决断路、短路的问题之后方能进行焊接。
这样做的好处是,保证了调试程序时不会受硬件接触不良等情况的影响。
由于第一次尝试完全使用汇编语言对AT89S52进行编程操作,对汇编语言的陌生给前期编程工作带来诸多不便。
汇编语言不同于C或其它高级语言,程序间的跳转,各种寄存器的压栈出栈都需要人工考虑,而这种疏漏编译器也不会给出任何提示,于是往往一些大意的疏忽,程序便无法达到预期的效果。
加之没有相关条件使用在线调试,也给故障排除带来一些障碍。
对此的体会是,确定是程序出现问题时,优先往程序间的跳转条件、重要寄存器等的现场保护、循环退出的条件方面考虑,寻找原因。
由于此次硬件电路设计采用低电平导通的PNP三极管,和74LS244电平驱动器,也没有将IO口做通用数据传输口用,故不需考虑上拉电阻的选用及将相应管脚写入高电平以正确接收数据的问题。
当然在调试的过程中合理的使用软件仿真机,熟练的设置程序断点,同时观察单片机各寄存器值的变化,可以极大方便我们查找程序漏洞,解决问题。
在书写代码的过程中,应该注意代码的规范化,尤其是使用汇编编程时,必须加上必要的注释,方便程序阅读及故障排查。
对于需要使用到的各个变量,必须在程序开头集中定义存储位置,以求一目了然,在新增变量的时候也不至于出现存储单元被重复使用而导致数据丢失的情况。
最后,看着忙碌数日得来的劳动成果乖乖的工作,确实蛮有成就感。
希望今后有更多的机会进行这样的实践实验。
一十、附录
;AT89S52CLOCK_FINAL.asm
;(ElectronicCalendarandClock)
;ReferenceforGrade2008,s.c.u.t.
;Key0(forshift/adjust)connectedtoINT1
;Key1(forun-flash/flash)connectedtoINT0
;学生姓名:
黄锦波,黄卓佳
;学生学号:
200830240380,200830240434
;分组编号:
007
;变量定义
TICK_CNTEQU20H;T0倍乘
;------------------
SECOND_BCDEQU21H;时间记录
MINUTE_BCDEQU22H
HOUR_BCDEQU23H
;------------------
DAY_BCDEQU24H;日期记录
MONTH_BCDEQU25H
YEAR_BCDEQU26H
;------------------
FLASH_FLAGEQU27H;是否闪烁
DIS_FLAGEQUR7;当前显示内容标志;DIS_FLAG:
0-时间;1-日期;2-闹钟;3-闹钟开关;4-秒表
;------------------
NSECOND_BCDEQU2BH;闹钟时间
NMINUTE_BCDEQU2CH
NHOUR_BCDEQU2DH
;------------------
TCC_BCDEQU2EH;秒表计时器
TBB_BCDEQU2FH
TAA_BCDEQU30H
;------------------
TIMER_FLAGEQU31H;秒表模式
TIMER_START_FLAGEQU32H;秒表开始
;------------------
ALAM_STATEEQU33H;闹钟开启标志
;------------------
DI_40HEQU34H;提示音延时变量
DI_41HEQU35H;延时
;------------------
ALAM_ON1EQU36H;闹钟状态显示
ALAM_ON2EQU37H
ALAM_ON3EQU38H
ALAM_OFF1EQU39H
ALAM_OFF2EQU3AH
ALAM_OFF3EQU3BH
;------------------
;中断向量表
ORG0000H
LJMPMAIN
ORG0003H
LJMPEX0_INT;portINT0
ORG000BH
LJMPT0_INT;portT0
ORG0013H
LJMPEX1_INT;portINT1
;主程序
ORG0030H
MAIN:
NOP;mainprogram
;初始化堆栈
MOVSP,#60H
;初始化变量
MOVSECOND_BCD,#00H;BCDof"second"
MOVMINUTE_BCD,#00H;BCDof"minute"
MOVHOUR_BCD,#00H;BCDof"hour"
MOVNSECOND_BCD,#00H;BCDof"second"
MOVNMINUTE_BCD,#00H;BCDof"minute"
MOVNHOUR_BCD,#06H;BCDof"hour"
MOVTCC_BCD,#00H;BCDof"second"
MOVTBB_BCD,#00H;BCDof"minute"
MOVTAA_BCD,#00H;BCDof"hour"
MOVTIMER_START_FLAG,#00H;秒表工作标志
MOVTIMER_FLAG,#00H;秒表模式标志
MOVDAY_BCD,#06H;BCDof"day"
MOVMONTH_BCD,#06H;BCDof"month"
MOVYEAR_BCD,#010H;BCDof"year"
MOVFLASH_FLAG,#00H;flagforun-flash/flash
MOVDIS_FLAG,#00H;flagforshift(time/date)
MOVALAM_ON1,#55H;BCDOF闹钟状态显示
MOVALAM_ON2,#01H
MOVALAM_ON3,#55H
MOVALAM_OFF1,#63H
MOVALAM_OFF2,#42H
MOVALAM_OFF3,#33H
MOVALAM_STATE,#00H;初始化闹钟状态为OFF
;------------------
MOVTL0,#0B0H;constantfor0.05s
MOVTH0,#3CH;65536-15536=50,000for12MHz
MOVTICK_CNT,#14H;timesofoverflow0.05*20=1s
MOVTMOD,#01H;Mode1forT0,TimerMode
SETBET0;openT0
SETBEX0;openINT0,Key1
SETBEX1;openINT1,Key0
SETBEA;totalopen
SETBPT0;priorityforT0,高优先级
SETBTR0;startT0,Run
SCAN_HOUR:
;闹钟扫描
MOVA,SECOND_BCD
CJNEA,#00H,SCANALARM
MOVA,MINUTE_BCD
CJNEA,#00H,SCANALARM
HOUR:
CLRP2.0
NOP;整点,滴
SETBP2.0
SCANALARM:
;闹钟扫描
MOVA,ALAM_STATE
JZSCAN_HOUR;闹钟开关已打开?
MOVA,NHOUR_BCD
CJNEA,HOUR_BCD,WAIT
MOVA,NMINUTE_BCD
CJNEA,MINUTE_BCD,WAIT
ALARM:
CLRP2.0;闹铃:
滴滴滴滴``````
SETBP2.0
CLRP2.0
SETBP2.0
CLRP2.0
SETBP2.0
CLRP2.0
SETBP2.0
NOP
NOP
NOP
WAIT:
SETBP2.0
SJMPSCAN_HOUR;waitforinterrupt
;-------------------------------------------------
;sub:
T0interrupt
;定时器0中断
T0_INT:
PUSHACC
MOVTL0,#0B0H;constantfor0.05s
MOVTH0,#3CH;Timer0重装载
MOVA,TIMER_START_FLAG
CJNEA,#01H,TIMER_NEXT;秒表模式?
LJMPTIMER_INC;秒表计时
TIMER_NEXT:
DJNZTICK_CNT,NOT_1S;isupto1second?
SJMPIS_1S
NOT_1S:
LJMPT0_RET
;1秒时间到
IS_1S:
MOVA,SECOND_BCD;takeBCDof"second"
CJNEA,#59H,IN3;isupto59seconds?
SJMPIN4
IN3:
LJMPSECOND_INC;秒加1
IN4:
MOVSECOND_BCD,#00H;秒进位
MOVA,MINUTE_BCD;takeBCDof"minute"
CJNEA,#59H,IN5;isupto59minutes?
SJMPIN6
IN5:
LJMPMINUTE_INC
IN6:
MOVMINUTE_BCD,#00H;分进位
MOVA,HOUR_BCD;takeBCDof"hour"
CJNEA,#23H,HOUR_INC;isupto23hours?
MOVHOUR_BCD,#00H;“时”进位
MOVA,MONTH_BCD;takeBCDof"month"
CJNEA,#02H,NOT_FEB;isFebruary?
;2月处理
;--------------------------
FEB:
NOP
ACALLBCD_DIV4;BCDof"yearin26H"dividedby4
MOVA,R3;remainderinR3
CJNEA,#00H,NOT_LEAP_Y;"00"meansleapyear
;闰年,29天
LEAP_Y:
MOVA,DAY_BCD;takeBCDof"day"inFeb.
CJNEA,#29H,DAY_INC;isupto29days(leapyear)?
MOVDAY_BCD,#01H;keepthefirstday
MOVMONTH_BCD,#03H;increase"month"
SJMPRESET_CNT
;非闰年
NOT_LEAP_Y:
MOVA,DAY_BCD;takeBCDof"day"inFeb.
CJNEA,#28H,DAY_INC;isupto28days(commonyear)?
MOVDAY_BCD,#01H;keepthefirstday
MOVMONTH_BCD,#03H;increase"month"
SJMPRESET_CNT
;---------------------------
;非2月处理
;30/31天?
NOT_FEB:
NOP;other"month"exceptFeb.
CJNEA,#04H,Y01;isApril?
AJMPMON_30D
Y01:
CJNEA,#06H,Y02;isJune?
AJMPMON_30D
Y02:
CJNEA,#09H,Y03;isSeptember?
AJMPMON_30D
Y03:
CJNEA,#11H,T11;isNovember?
AJMPMON_30D
;31天
T11:
MOVA,DAY_BCD;takeBCDof"day"
CJNEA,#31H,DAY_INC;isupto31days?
AJMPNEXT_MONTH
;30天
MON_30D:
MOVA,DAY_BCD;takeBCDof"day"
CJNEA,#30H,DAY_INC;isupto30days?
;天进位
NEXT_MONTH:
MOVDAY_BCD,#01H;keepthefirstday
MOVA,MONTH_BCD;takeBCDof"month"
CJNEA,#12H,MONTH_INC;isDecember?
;月进位
MOVMONTH_BCD,#01H;keepthefirstmonth
MOVA,YEAR_BCD;takeBCDof"year"
CJNEA,#99H,YEAR_INC;isupto99years?
MOVYEAR_BCD,#00H;keepthefirstyear
SJMPRESET_CNT
;年加1
YEAR_INC:
MOVA,YEAR_BCD;takeBCDof"year"
ADDA,#01H;increase"year"
DAA;adjustBCD
MOVYEAR_BCD,A;keep"year"
SJMPRESET_CNT
MONTH_INC:
MOVA,MONTH_BCD;takeBCDof"month"
ADDA,#01H;increase"month"
DAA;BCD码调整
MOVMONTH_BCD,A;keep"month"
SJMPRESET_CNT
DAY_INC:
MOVA,DAY_BCD;takeBCDof"day"
ADDA,#01H;increase"day"
DAA;BCD码调整
MOVDAY_BCD,A;keep"day"
SJMPRESET_CNT
HOUR_INC:
MOVA,HOUR_BCD;takeBCDof"hour"
ADDA,#01H;increase"hour"
DAA;BCD码调整
MOVHOUR_BCD,A;keep"hour"
SJMPRESET_CNT
MINUTE_INC:
MOVA,MINUTE_BCD;takeBCDof"minute"
ADDA,#01H;increase"minute"
DAA;BCD码调整
MOVMINUTE_BCD,A;keep"minute"
SJMPRESET_CNT
SECOND_INC:
MOVA,SECOND_BCD;takeBCDof"second"
ADDA,#01H;increase"second"
DAA;BCD码调整
MOVSECOND_BCD,A;saveback"second"
RESET_CNT:
MOVTICK_CNT,#14H;retrievetimesofoverflow
T0_RET:
POPACC
RETI
;--------------------------------------------------------------------
;秒表增
TIMER_INC:
TCC_INC:
MOVA,TCC_BCD;takeBCDof"0.05S"
CLRC
SUBBA,#95H
JZTBB_INC
MOVA,TCC_BCD
ADDA,#05H;increase"0.05S"
DAA;BCD码调整
MOVTCC_BCD,A;keep"0.05S"
AJMPTIMER_OUT
TBB_INC:
MOVTCC_BCD,#00H
MOVA,TBB_BCD;takeBCDof"SECOND"
CLRC
SUBBA,#59H
JZTAA_INC
MOVA,TBB_BCD
ADDA,#01H;increase"SECOND"
DAA;BCD码调整
MOVTBB_BCD,A;keep"SECOND"
AJMPTIMER_OUT
TAA_INC:
MOVTBB_BCD,#00H
MOVA,TAA_BCD;takeBCDof"MINUTE"
CLRC
SUBBA,#59H
JZTDD_INC
MOVA,TAA_B