当前位置:文档之家› 最新毕业设计:基于单片机的电子日历时钟

最新毕业设计:基于单片机的电子日历时钟

一课程设计题目:电子日历时钟二实现的功能:基本功能:(1)显示北京时间,并且能够校准时间;(2)程序使用汇编语言;(3)显示的时、分、秒之间以及年、月、日间以小数点分隔;(4)显示公历日期,并且能够校准日期;发挥功能:(5)运动秒表;(6)闹钟功能;(7)自动整点报时。

三课程设计的目的:课程标志性内容的设计理解和综合运用,对所学内容进行一次实操,学以致用。

四、设计方案说明1、硬件部分(1)采用6位LED数码管显示日期或者时间。

(2)显示器的驱动采用“动态扫描驱动”,且采用“一键多用”的设计方案,系统电路大为简化。

使用小数点表示闹钟设置状态;(3)电路连接使用PCB,使电路连接简洁美观2、软件部分(1)“时钟”基准时间由单片机内部的定时中断提供,考虑因素:定时时间是“秒”的整除数,且长短适宜。

最长不能超过16位定时器的最长定时时间;最短不能少于中断服务程序的执行时间。

基准时间越短,越有利于提高时钟的运行精确度。

基准时间定为0.05秒。

(2)用一个计数器对定时中断的次数进行计数,由基准时间为0.05秒知计数值为20即可实现实现“秒”定时,同理进行“分”﹑“时”定时,以及“日”﹑“月”﹑“年”定时。

(3)LED 数码管显示器采用“动态扫描驱动”考虑问题:驱动信号的维持时间必须大于“起辉时间”(电流大起辉时间短),而驱动信号的间歇时间必须小于“余辉时间”(电流大余辉时间长),但驱动电流大小受硬件电路能力和LED数码管极限功耗的制约。

(4)动态扫描显示方式在更新显示内容时,考虑到因LED数码管余辉的存在可能会造成显示字符的模糊,所以新内容写入显示器之前将所有的LED数码管熄灭。

(5)关于自动识别“月大﹑月小”和“平年﹑润年”问题的考虑a)月大和月小2月另外计算;4月﹑6月﹑9月﹑11 月为月小30天,其余为月大31天。

b)平年和润年(年号能被4整除的就是润年)平年的2月为28天;润年的2月为29天。

五、使用说明实物图请参照后面附带图片,从左至右为按键K2,K1,K0,以两个LED显示器为一组,左中右显示时分秒或者年月日,还有闹钟和秒表K2:复位 K1:设置闪烁 K0:切换时间/日期或者调整时间/日期初始状态:接上电源之后,日期默认为10年6月21日,时间为0时0分秒,闹钟2点整但默认关闭,秒表为0状态(1)显示状态切换:不断按K0键就会依次循环显示下面的状态初始状态时间日期闹钟时间闹钟状态秒表状态(2)调节时间,日期:按K0键切换到想要调节的显示状态,再按K1键选择要修改的位,不断按K1键会按左闪烁.中闪烁.右闪烁.确定.四个状态切换,闪烁的位可以修改,按K0键可以实现增加,不能递减,例如要调慢时间要按到循环到较慢时间。

(3)闹钟使用:闹钟默认响的时间为一分钟,闹钟的时间设置同时间日期的调节,只需把状态切换到闹钟时间的状态,闹钟的开关先按K0键切换到屏幕显示为OFF的状态,如下:再按K1可切换到开状态,如下图,再按K1可关闭,不断循环(4)秒表:K0键按4下就可切换到秒表状态,出示为0,此时按下K1键就可开始计时,再按一下K1键可停止,此时K1为秒表开关,按K0键可再切换显示其他。

六、硬件连接图1、原理图2、pcb图3、实物图1.主程序2.定时器0中断子程序3.外部中断0子程序4.外部中断1子程序八、性能测试与故障排查1、硬件部分问题:断路。

现象:程序下载完之后可以工作但是6个LED显示器有2个没亮。

分析:因为其他几个显示器完全正常,这两个则完全没亮,所以推断是位选的线路出故障。

检测:用万用表测试各点电压,着重测试两条位选线路的断路与短路情况,最终发现两处断路。

解决:焊锡接上,最终全亮2、软件部分偶数组实现基础功能的程序老师已经提供,该程序基本没有多大的问题,就是里面的几个参数需要修改,同时还有一个小bug。

修改一:由于提供的程序所默认采取的晶振计数频率是6MHz,但是所提供的现实原件则是12MHz,所以根据晶振的不同,定时器的定时时间变为0.05s。

按照该程序直接跑的话,计数时间为0.5s。

这就需要设置计数次数TICK_CNT为#14H,即0.05s*20=1s。

代码段:MOV TICK_CNT,#14H修改二:程序默认设置的外部中断延时过短,导致操作过于“灵敏”,也即按键K0、K1按下时,跳变过快。

这里所说的延时是中断子程序EX0_INT和EX1_INT中的语句LCALL DIS_DELAY。

解决这个情况只需修改DELAY 次数,则DIS_DELAY:MOV D_CNT_DIS,#10H。

修改三:观察实物电路工作发现每一位:LED数码管的小数点都是亮的,没有起到用小数点区分时间/日期中的时分秒/年月日。

要解决这个问题,在显示子程序中TSA代码段的MOV Rx A前插入语句ADD A,#80H(x=1、2、4、6)。

以及加上发挥部分的拓展功能:秒表和闹钟。

九、原件清单十、心得体会与总结这个学期做了两个与汇编有关的课程设计(不过这次是大作业),一次是开学初的微机原理课程设计,还有就是这次单片机原理大作业。

上次基本上只与程序打交道,硬件部分实操不多。

而这次大作业则是硬件、软件两方面都有兼顾,且两者所花的时间也都不少。

虽然从老师那已经获取了原理图和程序,但这是我们第一次比较系统的从熟悉软件操作到软硬件设计了解整个流程。

硬件部分,由于先前我们都没有操作过protel之类的软件,所以一切从零开始,针对这次大作业需要,学习了protel软件的基本操作、原理图的绘制修改、原件的封装以及原件集成库的创建,当然还有PCB板的排线。

之后就是PCB图打印,电路板热压制、腐蚀、钻孔,元器件的焊接。

流程很简洁,过程很纠结。

我们一步一个脚印地制作着,生怕哪个步骤出错而导致前功尽废。

不过在我们不懈努力下终于走完。

但是焊接的不仔细——两个电阻虚焊,使后来电路出现问题,也排查了好久,需要记住教训。

软件部分,虽然老师已经给了具备基本功能的程序,但是仍需看懂弄懂,后期才能更好地发现问题以及修改添加功能。

我发现这个过程也并非一件易事,清楚认识每一句的作用也需要经常查阅书籍。

另外在硬件焊接已经实现后我们把两者结合在一起,通过下载器把程序烧进52单片机中实现既定功能,发现上面故障排查中出现的问题,继而针对每个问题分别从软硬件寻找解决方法,这个过程我认为收获更大,能让我们更清楚熟悉软硬件两者的运作方法。

而且我俩分工是按硬件、软件而分的,自个儿认为分工尚算明确,各司其职。

十一、程序附录;wahaha.asm; (Electronic Calendar and Clock); Reference for Grade 2008, s.c.u.t.; Key0(for shift/adjust) connected to INT1; Key1(for un-flash/flash) connected to INT0; 学生姓名:陈晓伟、冯劲增; 学生学号:200830240144,200830240229; 分组编号:004;变量定义TICK_CNT EQU 20H ;T0倍乘;------------------SECOND_BCD EQU 21H ;时间记录MINUTE_BCD EQU 22HHOUR_BCD EQU 23HDAY_BCD EQU 24H ;日期记录MONTH_BCD EQU 25HYEAR_BCD EQU 26H;------------------FLASH_FLAG EQU 27H ;是否闪烁DIS_FLAG EQU R7 ;当前显示内容标志 ;DIS_FLAG: 0-时间;1-日期;2-闹钟;3-闹钟开关;4-秒表;------------------NSECOND_BCD EQU 2BH ;闹钟时间NMINUTE_BCD EQU 2CHNHOUR_BCD EQU 2DH;------------------TCC_BCD EQU 2EH ;秒表计时器TBB_BCD EQU 2FHTAA_BCD EQU 30H;------------------TIMER_FLAG EQU 31H ;秒表模式TIMER_START_FLAG EQU 32H ;秒表开始;------------------ALAM_STATE EQU 33H ;闹钟开启标志;------------------DI_40H EQU 34H ;提示音延时变量DI_41H EQU 35H ;延时;------------------ALAM_ON1 EQU 36H ;闹钟状态显示ALAM_ON2 EQU 37HALAM_ON3 EQU 38HALAM_OFF1 EQU 39HALAM_OFF2 EQU 3AHALAM_OFF3 EQU 3BH;------------------;中断向量表ORG 0000HLJMP MAINORG 0003HLJMP EX0_INT ; port INT0ORG 000BHLJMP T0_INT ; port T0ORG 0013HLJMP EX1_INT ; port INT1;主程序ORG 0030HMAIN: NOP ; main program ;初始化堆栈MOV SP,#60H;初始化变量MOV SECOND_BCD,#00H ; BCD of "second"MOV MINUTE_BCD,#00H ; BCD of "minute"MOV HOUR_BCD,#00H ; BCD of "hour"MOV NSECOND_BCD,#00H ;闹钟BCD of "second"MOV NMINUTE_BCD,#00H ;闹钟 BCD of "minute"MOV NHOUR_BCD,#06H ;闹钟BCD of "hour"MOV TCC_BCD,#00H ; 秒表BCD of "second"MOV TBB_BCD,#00H ; 秒表BCD of "minute"MOV TAA_BCD,#00H ; 秒表BCD of "hour"MOV TIMER_START_FLAG,#00H ;秒表工作标志MOV TIMER_FLAG,#00H ;秒表模式标志MOV DAY_BCD,#21H ; BCD of "day"MOV MONTH_BCD,#06H ; BCD of "month"MOV YEAR_BCD,#010H ; BCD of "year"MOV FLASH_FLAG,#00H ; flag for un-flash/flash MOV DIS_FLAG,#00H ; flag for shift(time/date)MOV ALAM_ON1,#55H ; BCD OFF 闹钟状态显示MOV ALAM_ON2,#01HMOV ALAM_ON3,#55HMOV ALAM_OFF1,#63HMOV ALAM_OFF2,#42HMOV ALAM_OFF3,#33HMOV ALAM_STATE,#00H ;初始化闹钟状态为OFF;------------------MOV TL0,#0B0H ; constant for 0.05sMOV TH0,#3CH ; 65536-15536=50,000 for 12MHz MOV TICK_CNT,#14H ; times of overflow 0.05*20=1sMOV TMOD,#01H ; Mode 1 for T0, Timer ModeSETB ET0 ; open T0SETB EX0 ; open INT0, Key1SETB EX1 ; open INT1, Key0SETB EA ; total openSETB PT0 ; priority for T0,高优先级SETB TR0 ; start T0, RunSCAN_HOUR: ;闹钟扫描MOV A,SECOND_BCDCJNE A,#00H,SCANALARMMOV A,MINUTE_BCDCJNE A,#00H,SCANALARMHOUR:CLR P2.0NOP ;整点,滴SETB P2.0SCANALARM: ;闹钟扫描MOV A,ALAM_STATEJZ SCAN_HOUR ;闹钟开关已打开?MOV A,NHOUR_BCDCJNE A,HOUR_BCD,WAITMOV A,NMINUTE_BCDCJNE A,MINUTE_BCD,WAITALARM:CLR P2.0 ;闹铃:滴滴滴滴`````` SETB P2.0CLR P2.0SETB P2.0CLR P2.0SETB P2.0CLR P2.0SETB P2.0NOPNOPNOPWAIT:SETB P2.0SJMP SCAN_HOUR ; wait for interrupt; -------------------------------------------------; sub: T0 interrupt; 定时器0中断T0_INT:PUSH ACCMOV TL0,#0B0H ; constant for 0.05s MOV TH0,#3CH ; Timer 0重装载MOV A,TIMER_START_FLAGCJNE A,#01H,TIMER_NEXT ;秒表模式?LJMP TIMER_INC ;秒表计时TIMER_NEXT:DJNZ TICK_CNT,NOT_1S ; is up to 1 second ?SJMP IS_1SNOT_1S:LJMP T0_RET; 1秒时间到IS_1S:MOV A,SECOND_BCD ; take BCD of "second"CJNE A,#59H,IN3 ; is up to 59 seconds ?SJMP IN4IN3:LJMP SECOND_INC ; 秒加1IN4:MOV SECOND_BCD,#00H ; 秒进位MOV A,MINUTE_BCD ; take BCD of "minute"CJNE A,#59H,IN5 ; is up to 59 minutes ?SJMP IN6IN5: LJMP MINUTE_INCIN6: MOV MINUTE_BCD,#00H ; 分进位MOV A,HOUR_BCD ; take BCD of "hour"CJNE A,#23H,HOUR_INC ; is up to 23 hours ?MOV HOUR_BCD,#00H ; "时"进位MOV A,MONTH_BCD ; take BCD of "month"CJNE A,#02H,NOT_FEB ; is February ?;2月处理;--------------------------FEB: NOPACALL BCD_DIV4 ; BCD of "year in 26H" divided by 4MOV A,R3 ; remainder in R3CJNE A,#00H,NOT_LEAP_Y ; "00" means leap year;闰年,29天LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.CJNE A,#29H,DAY_INC ; is up to 29 days (leap year)?MOV DAY_BCD,#01H ; keep the first dayMOV MONTH_BCD,#03H ; increase "month"SJMP RESET_CNT;非闰年NOT_LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.CJNE A,#28H,DAY_INC ; is up to 28 days (common year)?MOV DAY_BCD,#01H ; keep the first dayMOV MONTH_BCD,#03H ; increase "month"SJMP RESET_CNT;---------------------------;非2月处理;30/31天?NOT_FEB:NOP ; other "month" except Feb.CJNE A,#04H,Y01 ; is April ?AJMP MON_30DY01: CJNE A,#06H,Y02 ; is June ?AJMP MON_30DY02: CJNE A,#09H,Y03 ; is September ?AJMP MON_30DY03: CJNE A,#11H,T11 ; is November ?AJMP MON_30D;31天T11: MOV A,DAY_BCD ; take BCD of "day"CJNE A,#31H,DAY_INC ; is up to 31 days ?AJMP NEXT_MONTH;30天MON_30D:MOV A,DAY_BCD ; take BCD of "day"CJNE A,#30H,DAY_INC ; is up to 30 days ?;天进位NEXT_MONTH: MOV DAY_BCD,#01H ; keep the first day MOV A,MONTH_BCD ; take BCD of "month"CJNE A,#12H,MONTH_INC ; is December ?; 月进位MOV MONTH_BCD,#01H ; keep the first monthMOV A,YEAR_BCD ; take BCD of "year"CJNE A,#99H,YEAR_INC ; is up to 99 years ?MOV YEAR_BCD,#00H ; keep the first yearSJMP RESET_CNT;年加1YEAR_INC: MOV A,YEAR_BCD ; take BCD of "year"ADD A,#01H ; increase "year"DA A ; adjust BCDMOV YEAR_BCD,A ; keep "year"SJMP RESET_CNTMONTH_INC: MOV A,MONTH_BCD ; take BCD of "month"ADD A,#01H ; increase "month"DA A ; BCD码调整MOV MONTH_BCD,A ; keep "month"SJMP RESET_CNTDAY_INC: MOV A,DAY_BCD ; take BCD of "day"ADD A,#01H ; increase "day"DA A ; BCD码调整MOV DAY_BCD,A ; keep "day"SJMP RESET_CNTHOUR_INC: MOV A,HOUR_BCD ; take BCD of "hour"ADD A,#01H ; increase "hour"DA A ; BCD码调整MOV HOUR_BCD,A ; keep "hour"SJMP RESET_CNTMINUTE_INC: MOV A,MINUTE_BCD ; take BCD of "minute"ADD A,#01H ; increase "minute"DA A ; BCD码调整MOV MINUTE_BCD,A ; keep "minute"SJMP RESET_CNTSECOND_INC: MOV A,SECOND_BCD ; take BCD of "second"ADD A,#01H ; increase "second"DA A ; BCD码调整MOV SECOND_BCD,A ; save back "second"RESET_CNT: MOV TICK_CNT,#14H ; retrieve times of overflowT0_RET:POP ACCRETI;--------------------------------------------------------------------;秒表增TIMER_INC:TCC_INC:MOV A,TCC_BCD ; take BCD of "0.05S"CLR CSUBB A,#95HJZ TBB_INCMOV A,TCC_BCDADD A,#05H ; increase "0.05S"DA A ; BCD码调整MOV TCC_BCD,A ; keep "0.05S"AJMP TIMER_OUTTBB_INC:MOV TCC_BCD,#00HMOV A,TBB_BCD ; take BCD of "SECOND"CLR CSUBB A,#59HJZ TAA_INCMOV A,TBB_BCDADD A,#01H ; increase "SECOND"DA A ; BCD码调整MOV TBB_BCD,A ; keep "SECOND"AJMP TIMER_OUTTAA_INC:MOV TBB_BCD,#00HMOV A,TAA_BCD ; take BCD of "MINUTE"CLR CSUBB A,#59HJZ TDD_INCMOV A,TAA_BCDADD A,#01H ; increase "MINUTE"DA A ; BCD码调整MOV TAA_BCD,A ; save back "MINUTE"AJMP TIMER_OUTTDD_INC:MOV TAA_BCD,00HTIMER_OUT: LJMP TIMER_NEXT ;返回定时器中断;------------------------------------------------------------------;-------------------------------------------------------------------; sub: LED Display;显示子程序DISPLAY:MOV A,DIS_FLAGCJNE A,#03H,DISPLAY2 ;选择不同字模MOV DPTR,#TAB2SJMP DISPLAY3DISPLAY2:MOV DPTR,#TAB ; set address of code table DISPLAY3:MOV A,DIS_FLAG ; take flag for shiftCJNE A,#00H,DISP_DATE ; "00" 当前显示内容为时间;R0: point to display bufferDISP_TIME: MOV R0,#SECOND_BCD ; beginning from "second"SJMP TSADISP_DATE:CJNE A,#01H,DISP_ALAM ; "01" 当前显示内容为日期 MOV R0,#DAY_BCD ; "FF" for showing dateSJMP TSA;显示时间或日期DISP_ALAM:CJNE A,#02H,DISP_ALAM_SET ; "02" 当前显示内容为闹钟MOV R0,#NSECOND_BCD ; beginning from "second"SJMP TSADISP_ALAM_SET:CJNE A,#03H,DISP_TIMER ; "03" 当前显示内容为闹钟设置MOV A,ALAM_STATE ; 闹钟状态显示JZ SHOWOFFMOV R0,#ALAM_ON1 ; 显示"ON"SJMP TSASHOWOFF:MOV R0,#ALAM_OFF1 ;显示"OFF"SJMP TSADISP_TIMER: ;"04"当前显示内容为秒表MOV R0,#TCC_BCD ; beginning from "second"TSA: MOV A,@R0 ; begin from "day"ANL A,#0FH ; get the "low half byte"MOVC A,@A+DPTR ; take character from code tableMOV R1,A ; keep in R1 for DS6 showingMOV A,@R0SWAP AANL A,#0FH ; get the "high half byte"MOVC A,@A+DPTR ; take character from code table MOV R2,A ; keep in R2 for DS5 showing;---------------INC R0MOV A,@R0 ; next one from "month"ANL A,#0FH ; get the "low half byte"MOVC A,@A+DPTRMOV R3,A ; keep in R3 for DS4 showingMOV A,@R0SWAP AANL A,#0FH ; get the "high half byte"MOVC A,@A+DPTRMOV R4,A ; keep in R4 for DS3 showing;-------------INC R0MOV A,@R0 ; next one from "year"ANL A,#0FH ; get the "low half byte"MOVC A,@A+DPTRMOV R5,A ; keep in R5 for DS2 showingMOV A,@R0SWAP AANL A,#0FH ; get the "high half byte"MOVC A,@A+DPTRMOV R6,A ; keep in R6 for DS1 showing;---------------------;P1:位选线;P0:段选线NOPTDP: MOV P1,#0FFH ; close all showing///;Display DS6MOV A,ALAM_STATE ;是否显示闹钟状态位?(最末位小数点)JZ DIS_NEXTMOV A,R1ANL A,#7FHMOV R1,ADIS_NEXT:MOV A,R1MOV P0,A ; send character to DS6MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#03H,A02 ; "03" is flash on DS5&DS6SJMP A03A02: CJNE A,#03H,A04; ; "03" is flash on DS5&DS6A03: MOV A,TICK_CNT ; take Counter of overflow RRC AJNC A05 ; check bit C ( 1 or 0 )A04: MOV P1,#0dfH ; turn on DS6A05: LCALL DELAYMOV P1,#0FFH ; close all showing;Display DS5MOV P0,R2 ; send character to DS5MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#03H,B02 ; "03" is flash on DS5&DS6SJMP B03B02: CJNE A,#03H,B04B03: MOV A,TICK_CNT ; take times of overflow RRC AJNC B05 ; check bit C ( 1 or 0 )B04: MOV P1,#0efH ; turn on DS5B05: LCALL DELAYMOV P1,#0FFH ; close all showing;Display DS4MOV A,R3ANL A,#7FH ;该位增加小数点显示MOV P0,A ; send character to DS4MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#02H,C02 ; "02" is flash on DS3&DS4SJMP C03C02: CJNE A,#02H,C04C03: MOV A,TICK_CNT ; take times of overflow RRC AJNC C05 ; check bit C ( 1 or 0 )C04: MOV P1,#0f7H ; turn on DS4C05: LCALL DELAYMOV P1,#0FFH ; close all showing;Display DS3MOV P0,R4 ; send character to DS3MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#02H,D02 ; "02" is flash on DS3&DS4SJMP D03D02: CJNE A,#02H,D04D03: MOV A,TICK_CNT ; take times of overflow RRC AJNC D05 ; check bit C ( 1 or 0 )D04: MOV P1,#0fbH ; turn on DS3D05: LCALL DELAYMOV P1,#0FFH ; close all showing;Display DS2MOV A,R5ANL A,#7FH ;该位增加小数点显示MOV P0,A ; send character to DS2MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#01H,E02 ; "01" is flash on DS1&DS2SJMP E03E02: CJNE A,#01H,E04E03: MOV A,TICK_CNT ; take times of overflow RRC AJNC E05 ; check bit C ( 1 or 0 )E04: MOV P1,#0fdH ; turn on DS2E05: LCALL DELAYMOV P1,#0FFH ; close all showingMOV P0,R6 ; send character to DS1MOV A,FLASH_FLAG ; get flag of un-flash/flashCJNE A,#01H,F02 ; "01" is flash on DS1&DS2SJMP F03F02: CJNE A,#01H,F04F03: MOV A,TICK_CNT ; take times of overflow RRC AJNC F05 ; check bit C ( 1 or 0 )F04: MOV P1,#0feH ; turn on DS1F05: LCALL DELAYMOV P1,#0FFH ; close all showingRET;-------------------------------------------------------------------; ----------------------------------------; sub: delay (1.542ms for 12MHz, 3.084ms for 6MHz);延时子程序D_CNT_2 EQU 28HD_CNT_1 EQU 29HDELAY: MOV D_CNT_2,#03HD_LOOP2: MOV D_CNT_1,#0FFH ;[1]D_LOOP1: DJNZ D_CNT_1,D_LOOP1 ;[2]DJNZ D_CNT_2,D_LOOP2 ;[2]RET; ----------------------------------------; --------------------------------------------------------- ;外部中断0; sub: INT0 interrupt; 处理按键K0,切换时间/日期/闹钟/闹钟设置/秒表显示或者调整EX0_INT: NOP ; switch or adjust with date/time PUSH ACCPUSH PSWLCALL DIS_DELAY ; re-bounce (with LED display)JNB P3.3,OUT ; check port INT1;K0按下NOP ; inhibit INT1 ( use k0);---------------------------------------------------MOV A,FLASH_FLAGCJNE A,#00H,JUDGE_MODE ;有闪烁进入调整模式SET_DIS: ;无闪烁进入设置显示或秒表模式CLR P2.0 ;按键滴一声MOV DI_41H,#19HDI_LPO:MOV DI_40H,#0FFHDI_LP:DJNZ DI_40H,DI_LPDJNZ DI_41H,DI_LPOSETB P2.0;---------------------------------------------------MOV A,DIS_FLAGINC AMOV DIS_FLAG,ACJNE A,#04H,CROSSTIMER ;进入秒表?;---------------------------------------------------TIMER:MOV TIMER_FLAG,#01H ;进入秒表,秒表模式设置为开 LJMP EX0_RET ;退出;---------------------------------------------------CROSSTIMER: ;显示模式切换CJNE A,#05H,OUTMOV DIS_FLAG,#00H ;已到5需置零MOV TIMER_FLAG,#00HMOV A,TIMER_START_FLAGJNZ OUT ;秒表后台工作,暂停计数时退出则对秒表清零MOV TCC_BCD,#00H ; BCD of "second" 秒表清零MOV TBB_BCD,#00H ; BCD of "minute"MOV TAA_BCD,#00H ; BCD of "hour"OUT: LJMP EX0_RET ; 退出;--------------------------------------------------- JUDGE_MODE: ;进入调整模式MOV A,DIS_FLAG ; 读取当前显示内容为?(时间/日期/秒表/闹钟)CJNE A,#00H,JDATE ;是否进入时间调整00;--------------------------------------------------- JTIME: ;调整时间MOV A,FLASH_FLAG ; take flag of un-flash/flash ADH: CJNE A,#01H,ADM ; "03" for adjusting "hour"MOV A,HOUR_BCD ; take BCD of "hour"CJNE A,#23H,JH0 ; is up to 23 hours ?MOV HOUR_BCD,#00H ; keep the first hourLJMP JHFJH0: ADD A,#01H ; increase "hour"DA A ; adjust BCDMOV HOUR_BCD,A ; keep "hour"JHF: LJMP EX0_RET;-----------------------------------------ADM: CJNE A,#02H,ADS ; "02" for adjusting "minute"MOV A,MINUTE_BCD ; take BCD of "minute"CJNE A,#59H,JM0 ; is up to 59 minutes ?MOV MINUTE_BCD,#00H ; keep the first minuteLJMP JMFJM0: ADD A,#01H ; increase "minute"DA A ; adjust BCDMOV MINUTE_BCD,A ; keep "minute"JMF: LJMP EX0_RETADS: MOV A,SECOND_BCD ; take BCD of "second"CJNE A,#59H,JS0 ; is up to 59 seconds ?MOV SECOND_BCD,#00H ; keep the first secondLJMP JSFJS0: ADD A,#01H ; increase "second"DA A ; adjust BCDMOV SECOND_BCD,A ; keep "second"JSF: NOPLJMP EX0_RET;--------------------------------------------------- JALAM0: LJMP JALAMJDATE: CJNE A,#01H,JALAM0 ;是否进入日期调整01 JYY: NOP ; "01 to 06" is in flashMOV A,FLASH_FLAGCJNE A,#01H,JMM ; "01" for adjusting "year";调节年MOV A,YEAR_BCD ; take BCD of "year"CJNE A,#99H,YY0 ; is up to 99 year ?MOV YEAR_BCD,#00H ; keep the first yearLJMP YYFYY0: ADD A,#01H ; increase "year"DA A ; adjust BCDMOV YEAR_BCD,A ; keep "year"YYF: LJMP EX0_RET;--------------------------------------- JMM: CJNE A,#02H,JDD ; "02" for adjusting "month";调节月MOV A,MONTH_BCD ; take BCD of "month"CJNE A,#12H,MM0 ; is December ?MOV MONTH_BCD,#01H ; keep the first monthLJMP MMFMM0: ADD A,#01H ; increase "month"DA A ; adjust BCDMOV MONTH_BCD,A ; keep "month"MMF: LJMP EX0_RET;---------------------------------------JDD: CJNE A,#03H,AA1 ; "03" for adjusting "day"LJMP BB1AA1: LJMP ADH ;BB1: MOV A,MONTH_BCD ; first, should take "month"CJNE A,#02H,NFB ; is February ?IFB: NOPACALL BCD_DIV4 ; BCD of "year in YEAR_BCD" divided by 4MOV A,R3 ; remainder in R3CJNE A,#00H,ANG ; "00" means leap yearARN: MOV A,DAY_BCD ; take BCD of "day"CJNE A,#29H,D0A ; is up to 29 days in Feb.?LJMP D0BD0A: LJMP DDAD0B: LJMP DD1ANG: MOV A,DAY_BCD ; take BCD of "day"CJNE A,#28H,D0A ; is up to 28 days in Feb.?LJMP DD1NFB: NOP ; check "little/large" monthCJNE A,#04H,Y04 ; is April ?LJMP AD1Y04: CJNE A,#06H,Y05 ; is June ?LJMP AD1Y05: CJNE A,#09H,Y06 ; is September ?LJMP AD1Y06: CJNE A,#11H,Y07 ; is November ?LJMP AD1Y07: NOP ; for "large" monthMOV A,DAY_BCD ; take BCD of "day"CJNE A,#31H,D0A ; is up to 31 days ?LJMP DD1AD1: NOP ; for "little" month MOV A,DAY_BCD ; take BCD of "day"CJNE A,#30H,D0A ; is up to 30 days ? DD1: MOV DAY_BCD,#01H ; keep the first day LJMP DDFDDA: ADD A,#01H ; increase "day"DA A ; adjust BCDMOV DAY_BCD,A ; keep "day"DDF: LJMP EX0_RET;--------------------------------------------------- JALAM: ;调整闹钟MOV A,FLASH_FLAG ; take flag of un-flash/flash NADH: CJNE A,#01H,NADM ; "03" for adjusting "hour"MOV A,NHOUR_BCD ; take BCD of "hour"CJNE A,#23H,NJH0 ; is up to 23 hours ?MOV NHOUR_BCD,#00H ; keep the first hourLJMP NJHFNJH0: ADD A,#01H ; increase "hour"DA A ; adjust BCDMOV NHOUR_BCD,A ; keep "hour"NJHF: LJMP EX0_RET;----------------------------------------- NADM: CJNE A,#02H,NADS ; "02" for adjusting "minute"MOV A,NMINUTE_BCD ; take BCD of "minute"CJNE A,#59H,NJM0 ; is up to 59 minutes ?MOV NMINUTE_BCD,#00H ; keep the first minuteLJMP NJMFNJM0: ADD A,#01H ; increase "minute"DA A ; adjust BCDMOV NMINUTE_BCD,A ; keep "minute"NJMF: LJMP EX0_RETNADS: MOV A,NSECOND_BCD ; take BCD of "second"CJNE A,#59H,NJS0 ; is up to 59 seconds ?MOV NSECOND_BCD,#00H ; keep the first secondLJMP NJSFNJS0: ADD A,#01H ; increase "second"DA A ; adjust BCDMOV NSECOND_BCD,A ; keep "second"NJSF: NOPLJMP EX0_RET;---------------------------------------------------EX0_RET:NOP ;中断退出POP PSWPOP ACCRETI;---------------------------------------------------;---------------------------------------------------; sub: INT1 interrupt; 处理按键K1,设置闪烁EX1_INT:NOP ; revise flag(00 to 06) in FLASH_FLAGPUSH ACCPUSH PSWJNB P3.2,EX1_RET ; check port INT0LCALL DIS_DELAY ; re-bounce (with LED display);;K1按键按下NOP ; inhibit INT0 (use k1)MOV A,DIS_FLAGCJNE A,#03H,TIMER_START0 ;非设置闹钟开关模式?MOV A,ALAM_STATECPL A ;取非ANL A,#01H ;保留最后MOV ALAM_STATE,A ;设置闹钟开关AJMP DI_START ;提示音后退出;--------------------------------------------------- TIMER_START0:MOV A,TIMER_FLAGCJNE A,#01,FLASH_SHIFT ;非秒表模式?TIMER_START:MOV A,TIMER_START_FLAGCPL AANL A,#01H ;保留最低位MOV TIMER_START_FLAG,A ;设置秒表开关;---------------------------------------------------DI_START:CLR P2.0 ;按键滴一声MOV DI_41H,#19HDI_LOOPO:MOV DI_40H,#0FFHDI_LOOP:DJNZ DI_40H,DI_LOOPDJNZ DI_41H,DI_LOOPOSETB P2.0AJMP EX1_RET ;退出;--------------------------------------------------- FLASH_SHIFT: ;进入切换闪烁MOV A,FLASH_FLAG ; take flag of un-flash/flashCJNE A,#00H,ED1 ; "00" 无闪烁MOV FLASH_FLAG,#01H ; 设置1,2号数码管闪烁SJMP EX1_RETED1: CJNE A,#01H,ED2 ; "01" 1,2号闪烁中。

相关主题