基于单片机的电子日历时钟
- 格式:docx
- 大小:1.09 MB
- 文档页数:30
论文题目基于单片机的电子万年历(英文)Design of Electronic Calendar basedon single Chip Microcomputer摘要现今信息技术飞速发展,时间和每一个人都有非常密切的相互联系,时间对任何人都有着非常重要的影响。
随着科技的快速发展,流逝的时间,我们从根据太阳来判断时间,发展到了用钟摆看时间,到现在又有了各种电子表等。
当各类电子表在我们生活中广泛应用的时候,电子万年历的的出现又把我们引入到一个全新的时代。
电子万年历是一种使用非常广泛的日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,还具有时间校准等功能。
本设计是基于51系列的单片机进行的电子万年历设计,主要由时钟芯片DS1302采集数据到单片机进行处理再通过LCD1602显示出来。
电子万年历的软件部分是使用c语言编写,主要用到的硬件电路有时钟芯片DS1302、液晶显示LCD1602,主控制芯片AT89C51,还有按键。
关键词:单片机, LCD602, AT89C51 ,DS302AbstractNowadays information technology develops rapidly, and time and everyone have very close interconnections, and time has a very important influence on anyone. With the rapid development of science and technology, the time elapsed, we judge the time according to the sun, develop to use the pendulum to watch the time, and now have all kinds of electronic watches and so on. When all kinds of electronic watches are widely used in our lives, the advent of electronic calendar brings us to a whole new era. Electronic calendar is a kind of widely used daily timing tool, which is becoming more and more popular in modern society. It can time the year, month, day, Sunday, hour, minute, second, also have leap year compensation and so on many functions, still have time calibration and so on function.This design is based on the electronic calendar design of 51 series of single-chip microcomputer, mainly by the clock chip DS1302 collecting data to the single chip microcomputer for processing and then through LCD1602. The software part of the electronic calendar is written in c language. The main hardware circuits used are clock chip DS1302, liquid crystal display LCD1602, master control chip AT89C51, and buttons.Key words:Microcontroller;LCD1602;AT89C51;DS1302目录目录 (3)第1章绪论 (4)1.1背景及目的 (4)1.1.1课题研究背景 (4)1.1.2选题的意义及目的 (4)1.2 国内外发展现状及水平 (4)第2章系统的方案选择及论证 (6)2.1 单片机芯片选择 (6)2.2 时钟芯片的选择与论证 (6)2.3 显示模块的选择与论证 (6)2.4 电路设计最终方案 (7)第3章系统的硬件设计与实现 (8)3.1 电路设计框图 (8)3.2系统硬件概述 (8)3.3 系统的电路设计 (8)3.3.1 系统总体电路设计图 (9)3.3.2单片机主控制模块 (9)3.3.3 时钟电路模块 (12)3.3.4 显示模块 (16)第4章系统的软件设计 (19)4.1 程序流程框图: (19)第5章Proteus软件仿真与测试 (22)5.1 仿真软件介绍 (22)5.2 Proteus 仿真效果 (22)第6章总结与体会 (24)参考文献 (25)附录1:程序 ..................................................... 错误!未定义书签。
基于单片机的电子万年历设计一、概述随着科技的快速发展和人们对生活品质的追求,电子设备在日常生活中扮演着越来越重要的角色。
电子万年历作为一种集日期、时间显示于一体的实用电子产品,已经深入到人们的日常生活和工作中。
传统的机械式日历已经无法满足现代人对时间精确性和功能多样性的需求,基于单片机的电子万年历设计应运而生,成为了当前研究的热点之一。
基于单片机的电子万年历设计,旨在利用单片机(如STC89CAT89C51等)的强大计算和控制能力,结合液晶显示屏(LCD)、按键输入等外设,实现时间的准确显示、日期的自动更新、闹钟提醒、温度显示等多样化功能。
该设计不仅具有高度的集成性和可靠性,而且能够通过编程实现各种定制化的功能,满足不同用户的需求。
本文将对基于单片机的电子万年历设计进行详细的介绍和分析,包括设计思路、硬件组成、软件编程等方面。
通过本文的阅读,读者可以了解电子万年历的基本原理和设计方法,掌握单片机在电子万年历设计中的应用技巧,为实际的开发工作提供有益的参考和借鉴。
1.1 研究背景与意义随着科技的不断进步,人们日常生活和工作中对于时间的精度和便捷性的要求日益提高。
传统的机械式日历和简单的电子时钟已经无法满足现代生活的需求。
电子万年历作为一种集时间显示、日历查询、定时提醒等多功能于一体的电子装置,在日常生活、工作乃至科研领域都具有广泛的应用价值。
基于单片机的电子万年历设计,不仅可以提供准确的时间显示,还能实现复杂的日期计算、农历显示、节假日提示等功能,极大地提高了时间管理的效率和便捷性。
单片机作为一种集成度高、功耗低、价格适中的微型计算机,非常适合用于小型化、智能化的电子产品设计,如电子万年历。
本研究的意义在于,通过对基于单片机的电子万年历的设计研究,可以推动微型计算机技术和电子时钟技术的融合发展,提升电子产品的智能化水平,满足人们日益增长的生活和工作需求。
同时,该研究还可以为相关领域的技术人员提供参考和借鉴,推动电子万年历产品的不断创新和优化。
数字钟、万年历制作(基于单片机)电路原理图:程序://********************20131206****数字钟程序#pragma SMALL#include <reg51.h>#include <absacc.h>#include <intrins.h>//********************************************************* *********编译预处理void display(unsigned char *p); //显示函数,P为显示数据首地址unsigned char keytest(); //按键检测函数unsigned char search(); //按键识别函数void alarm(); //闹钟判断启动函数void ftion0(); //始终修改函数void ftion1(); //闹钟修改函数void ftion3(); //日期修改函数void cum(); //加1修改函数void minus(); //减1修改函数void jinzhi(); //进制修改函数void riqi(); //日期void stopwatch(); //秒表函数//********************************************************* *******函数声明sbit P2_7=P2^7;//********************************************************* *******端口定义unsigned char clockbuf[3]={0,0,0};unsigned char bellbuf[3]={0,0,0};unsigned char date[3]={1,1,1}; //日期存放数组unsigned char stop[3]={0,0,0};unsigned char msec1,msec2;unsigned char timdata,rtimdata,dtimdata;unsigned char count;unsigned char *dis_p;unsigned char or; //12进制控制标志unsigned char ri; //日期显示控制标志位unsigned char mb; //秒表控制标志位bit arm,rtim,rhour,rmin,hour,min,sec,day,mon,year; //定义位变量//********************************************************* *****全局变量定义void main(){unsigned char a;or=0; //12进制修改标志清零ri=0;mb=0;P2_7=0;arm=0;msec1=0;msec2=0;timdata=0;rtimdata=0;count=0;TMOD=0x12;TL0=0x06;TH0=0x06;TH1=(65536-10000)/256;TL1=(65536-10000)%256;EA=1;ET0=1;ET1=1;TR0=1;TR1=0;dis_p=clockbuf;while(1){a=keytest();if(a==0x78) //判断是否有键按下{display(dis_p);if(arm==1) alarm();}else{display(dis_p);a=keytest();if(a!=0x78){a=search();switch(a){case 0x00:ftion0();break;case 0x01:ftion1();break;case 0x02:cum();break;case 0x06:jinzhi();break;case 0x03:riqi();break;case 0x04:ftion3();break;case 0x05:minus();break;case 0x07:stopwatch();break;case 0x09:TR1=1;break;case 0x0a:TR1=0;break;case 0x0b:stop[0]=0;stop[1]=0;stop[2]=0;break;default:break;}}}}}//********************************************主函数【完】void display(unsigned char *p){unsigned char buffer[]={0,0,0,0,0,0};unsigned char k,i,j,m,temp;unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};buffer[0]=p[0]/10;buffer[1]=p[0]%10;buffer[2]=p[1]/10;buffer[3]=p[1]%10;buffer[4]=p[2]/10;buffer[5]=p[2]%10;if((sec==0)&&(min==0)&&(hour==0)&&(rmin==0)&&(rhour==0)&&( day==0)&&(mon==0)&&(year==0)) //没有修改标志,正常显示{for(k=0;k<3;k++){temp=0x01;for(i=0;i<6;i++){P0=0x00; //段选端口j=buffer[i];P0=led[j];P1=~temp; //位选端口temp<<=1;for(m=0;m<200;m++);}}}else //若有修改标志,则按以下标志分别显示{if(sec==1||day==1){P1=0x1f;i=buffer[5];P0=led[i];for(m=0;m<200;m++);P1=0x2f;j=buffer[4];P0=led[j];for(m=0;m<200;m++);}if(min==1||rmin==1||mon==1){P1=0x3b;i=buffer[2];P0=led[i];for(m=0;m<200;m++);P1=0x37;j=buffer[3];P0=led[j];for(m=0;m<200;m++);}if(hour==1||rhour==1||year==1) {P1=0x3e;i=buffer[0];P0=led[i];for(m=0;m<200;m++);P1=0x3d;j=buffer[1];P0=led[j];for(m=0;m<200;m++);}}}//**********************************LED显示函数【完】unsigned char keytest(){unsigned char c;P2=0x78; //检测是否有键按下c=P2;c=c&0x78;return(c);}//******************************************键盘检测函数【完】unsigned char search(){unsigned char a,b,c,d,e;c=0x3f;a=0; //行号while(1){P2=c;d=P2;d=d&0x07;if(d==0x03){b=0;break;} //列号else if(d==0x05){b=1;break;}else if(d==0x06){b=2;break;}a++;c>>=1;if(a==5){a=0;c=0x3f;}}e=a*3+b;do{display(dis_p);}while((d=keytest())!=0x78);return(e);}//***********************************************查键值函数【完】void alarm(){if((clockbuf[0]==bellbuf[0])&&(clockbuf[1]==bellbuf[1])){P2_7=1;rtim=1;if(count==10){count=0;P2_7=0;arm=0;rtim=0;}}}//****************************************闹钟判断启动函数【完】void ftion0(){TR0=0;rhour=0;rmin=0;dis_p=clockbuf;rtimdata=0;timdata++;switch(timdata){case 0x01:sec=1;break;case 0x02:sec=0;min=1;break;case 0x03:min=0;hour=1;break;case 0x04:timdata=0;hour=0;TR0=1;break;default:break;}}//*********************************************时钟设置函数【完】void ftion1(){if(TR0==0) TR0=1;sec=0;min=0;hour=0;dis_p=bellbuf;timdata=0;rtimdata++;switch(rtimdata){case 0x01:rmin=1;break;case 0x02:rmin=0;rhour=1;break;case 0x03:rtimdata=0;rhour=0;arm=1;dis_p=clockbuf;break;default:break;}}//*********************************************闹钟设置函数【完】void ftion3(){if(TR0==0) TR0=1;day=0;mon=0;year=0;dis_p=date;timdata=0;rtimdata=0;dtimdata++;switch(dtimdata){case 0x01:day=1;break;case 0x02:day=0;mon=1;break;case 0x03:mon=0;year=1;break;case 0x04:dtimdata=0;year=0;dis_p=clockbuf;break;default:break;}}//*************************************************日期修改函数【完】void minus(){if(sec==1){if(0==clockbuf[2]) clockbuf[2]=59;else clockbuf[2]--;}else if(min==1){if(0==clockbuf[1]) clockbuf[1]=59;else clockbuf[1]--;}else if(hour==1){if(or==0) //判断进制{if(0==clockbuf[0]) clockbuf[0]=23;else clockbuf[0]--;}if(or==1){if(1==clockbuf[0]) clockbuf[0]=12;else clockbuf[0]--;}}else if(rmin==1){if(bellbuf[1]==0) bellbuf[1]=59;else bellbuf[1]--;}else if(rhour==1){if(or==0){if(bellbuf[0]==0) bellbuf[0]=23;else bellbuf[0]--;}if(or==1){if(bellbuf[0]==1) bellbuf[0]=12;else bellbuf[0]--;}}else if(day==1){if(date[2]==1) date[2]=31;else date[2]--;}else if(mon==1){if(date[1]==1) date[1]=12;else date[1]--;}else if(year==1){if(date[0]==1) date[0]=99;else date[0]--;}}//*************************************减1修改功能函数【完】void cum(){if(sec==1){if(59==clockbuf[2]) clockbuf[2]=0;else clockbuf[2]++;}else if(min==1){if(59==clockbuf[1]) clockbuf[1]=0;else clockbuf[1]++;}else if(hour==1){if(or==0) //判断进制{if(23==clockbuf[0]) clockbuf[0]=0;else clockbuf[0]++;}if(or==1){if(12==clockbuf[0]) clockbuf[0]=1;else clockbuf[0]++;}}else if(rmin==1){if(bellbuf[1]==59) bellbuf[1]=0;else bellbuf[1]++;}else if(rhour==1){if(or==0){if(bellbuf[0]==23) bellbuf[0]=0;else bellbuf[0]++;}if(or==1){if(bellbuf[0]==12) bellbuf[0]=1;else bellbuf[0]++;}}else if(day==1){if(date[2]==31) date[2]=1;else date[2]++;}else if(mon==1){if(date[1]==12) date[1]=1;else date[1]++;}else if(year==1){if(date[0]==99) date[0]=0;else date[0]++;}}//*************************************加1修改功能函数【完】void jinzhi(){if(or==0) or=1;else or=0;}//***********************************进制修改控制函数【完】void riqi(){if(ri==0){dis_p=date;}if(ri==1){dis_p=clockbuf;}ri++;if(ri==2) ri=0;}//********************************日期控显示函数【完】void stopwatch(){if(mb==0){dis_p=stop;mb=1;}else{mb=0;dis_p=clockbuf;}}//************秒表**********秒表**********秒表函数【完】void clock() interrupt 1{EA=0;if(msec1!=0x14) msec1++; //6MHz晶振定时10mselse{msec1=0;if(msec2!=100) msec2++; //定时1selse{if(rtim==1) count++; //闹钟启动标志计时10smsec2=0;if(clockbuf[2]!=59) clockbuf[2]++;else{clockbuf[2]=0;if(clockbuf[1]!=59) clockbuf[1]++;else{clockbuf[1]=0;if(or==0){if(clockbuf[0]!=23) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}if(or==1){if(clockbuf[0]!=12) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}}}}}EA=1;}//*******************************定时器0中断函数【完】void miaobiao() interrupt 3{TH1=(65536-10000)/256;TL1=(65536-10000)%256;if(stop[2]!=99) stop[2]++;else{stop[2]=0;if(stop[1]!=59) stop[1]++;else{stop[1]=0;if(stop[0]!=59) stop[0]++;else stop[0]=0;}}}//***********************************定时器1中断函数【完】。
引言随着生活节奏的日益加快,人们的时间观也越来越重,同时对电子钟表、日历的需求也随之提高。
因此,研究实用电子时钟及其扩展应用,有着非常现实的意义,具有很大的实用价值。
本系统程序由主程序、中断服务函数和多个子函数构成。
主函数主要完成各子函数和中断函数的初始化。
定时中断函数主要完成时钟芯片的定时扫描及键盘扫描。
时钟芯片的读写函数主要是将时间、日历信息读出来,并把要修改具体值写入时钟芯片内部。
系统的硬件设计与电路原理电路设计框图系统硬件概述本电路是由AT89S52单片机为控制核心,具有在线编程功能、低功耗、能在3V的超低压工作。
时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
可产生年、月、日、周日、时、分、秒,具有使用寿命长、精度高和低功耗等特点,同时具有掉电自动保存功能。
主控制模块单片机主控制模块的设计AT89S52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3,MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
时钟电路模块时钟电路模块的设计DS1302的引脚排列如图3所示,其中Vcc1为后备电源,Vcc2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电;当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768KHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
(2)31 8 位暂存数据存储RAM(3)串行 I/O 口方式使得管脚数量最少(4)宽范围工作电压2.0 5.5V(5)工作电流 2.0V 时,小于300nA(6)读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式(7)8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配(8)简单 3 线接口(9)与 TTL 兼容Vcc=5V(10)可选工业级温度范围-40~+85优点:串行接口的日历时钟芯片,使用简单,接口容易,与微型计算机连线较少等特点,在单片机系统尤其是手持式信息设备中己得到了广泛的应用。
所以,最终选择串行时钟芯片DS1302,DS1302的管脚图如图2所示。
图2 DS1302管脚图1.2显示模块选择方案一:LED数码管显示数码管显示比较常用的是采用CD4511和74LS138实现数码转换,数码显示分动态显示和静态显示,静态显示具有锁存功能,可以使数据显示得很清楚,但浪费了一些资源。
目前单片机数码管普通采用动态显示。
编程简单,但只能显示数字,不能显示中文。
方案二:LCD1602能够显示英文和数字。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
所以最终选择LCD1602。
2.项目功能模块2.1 89C51模块Mcs-51单片机管脚图图如图3所示:单片机管脚图2.2 1602液晶显示模块1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
基于单片机控制的电子万年历设计1设计要求功能:电子万年历能显示阳历、时间、室温,并能表明是否是闰年,通过按键实现切换。
本课题以单片机为核心,设计并制作出智能LCD电子钟,具有以下基本功能:计时、秒、分、时、天、周、月、年;能进行时间、年份、日期、星期显示;能区分是否闰年;能检测室温并显示。
扩展功能部分可以通过控制按键使时间暂停、可以调整校正时间并通过按键切换轮流显示时间、年份、日期、星期。
2方案论证与对比2.1液晶显示器控制方式选择采用LCD液晶显示,具有超精致影像画质、十足平面显示、节省空间、节省能源等优点,但按控制方式不同,LCD可分为被动矩阵式LCD及主动矩阵式LCD两种。
可根据不同需要采用不同的方式。
方案一被动矩阵式LCD被动矩阵式LCD在亮度及可视角方面受到较大的限制,反应速度也较慢。
由于画面质量方面的问题,使得这种显示设备不利于发展为桌面型显示器,但成本低廉。
方案二主动矩阵式LCD目前应用比较广泛的主动矩阵式LCD,也称TFT-LCD(Thin Film Transistor-LCD,薄膜晶体管LCD)。
TFT液晶显示器是在画面中的每个像素内建晶体管,可使亮度更明亮、色彩更丰富及更宽广的可视面积。
与CRT显示器相比,LCD显示器的平面显示技术体现为较少的零件、占据较少的桌面及耗电量较小,但CRT技术较为稳定成熟。
相比之下,本设计当中选用方案二主动矩阵式LCD方式。
2.2 并行接口动态显示电路选择可以采取串行接口动态显示电路或者并行接口动态显示电路,比较如下:方案一串行接口动态显示电路利用8051系列单片机内部的串行接口,也可以实现动态显示及键盘处理。
这样不但可以节省8051的并行I/O接口,而且在大多数不用单行口的情况下,可免于扩展接口。
在这种方法中,串行口工作在方式0状态,相当于一个移位寄存器,其输入/输出通过RXD引脚,移位脉冲则由TXD输出。
每次输入或输出8位数据(一个字节)。
基于单片机控制的电子万年历摘要本设计是一个带温度显示的万年历电路系统,该电路具有年、月、日、星期、时、分、秒、闹钟显示和调整功能,并且还包含显示温度功能。
其中显示部分采用LCD1602显示,时钟部分采用DS1302时钟芯片,温度部分采用DS18B20单线温度传感器。
软件方面我们采用C语言编程,利用Keil uVision3软件编写C语言程序并且生成HEX文件。
先将程序在Proteus 仿真,通过之后再烧录到单片机中。
该设计的优点是充分利用了LCD1602的显示功能完成了万年历应该具有的功能并且还扩展了温度;不足之处是收到LCD1602显示功能的限制没能显示农历日期。
电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S51单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
关键词:万年历;AT89C51;液晶显示(LCD1602);温度传感器(DS18B20);时钟芯片(DS1302);proteus仿真;目录摘要 (1)目录 (1)1引言: (2)2设计方案 (3)2.2模块选择 (4)2.3方案框图 (4)3 软件实现 (5)3.1流程图 (5)3.2程序编写 (6)3.3运行程序生成hex文件 (12)4 proteus仿真 (13)4.1软件简介 (13)4.2 Proteus电路仿真与调试 (14)5 PCB制版 (21)5.1 绘制电路原理图并仿真调试 (21)5.2加载网络表及元件封装 (21)5.3规划电路板并设置相关参数 (23)5.4元件布局及调整 (24)5.5布线并调整 (25)5.6输出及制作PCB (26)总结 (27)参考文献 (28)致谢 (29)1引言:随着微电子技术的高速发展,单片机在国民经济的个人领域得到了广泛的运用。
#include<STC12C5A.h>#define uchar unsigned char#define uint unsigned int//----端口定义---sbit ACC_7=ACC^7;sbit RST1=P2^5;sbit IO=P2^6;sbit SCLK=P2^7;sbit k1=P3^2;sbit k2=P3^3;sbit k3=P2^2;sbit k4=P2^3;//uchar wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; // 数码的位选,左到右uchar tab_1302[7]={45,50,11,19,1,1,15};uchar tab_time[8]={0,0,10,0,0,10,0,0}; //时间uchar tab_day[8]={0,0,10,0,0,10,0,0,}; //年月日uchar tab_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0 1 2 3 4 5 6 7 8 9 - {"0123456789-"}////////////=============函数声明============////////////////void display_time();void delayms(uint);void display_day();void ds1302(); //获取DS1302的时间void ds1302_init(); //DS1302的初始化void write1302(uchar,uchar); //指定地址向DS1302写数据uchar read1302(uchar); //指定地址向DS1302读数据void ds1302();void int0_init();/////////=======中断初始化=======///////////void int0_init(){EX0=1;IT0=1;EX1=1;IT1=1;EA=1;}///////////========时间显示======///////////// void display_time(){P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);}//////////=========延时函数========//////////////// void delayms(uint x){int i,j;for(i=x;i>=0;i--)for(j=0;j<=110;j++);}//////////=======日期显示======///////////void display_day(){P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////////=========DS1302初始化======//////////// void ds1302_init() //DS1302初始化,设置初始时间{uchar i,add;add=0x80;write1302(0x8e,0x00);for(i=0;i<7;i++){write1302(add,tab_1302[i]);add+=2;}/* write1302(0x80,0x50); // 秒...write1302(0x82,0x59); // 分write1302(0x84,0x23); // 时write1302(0x86,0x19); // 日write1302(0x88,0x01); // 月write1302(0x8a,0x01); // 周write1302(0x8c,0x15); // 年*/write1302(0x8e,0x80);}//////////============从DS1302获取数据============///////////// uchar read1302(uchar add){uchar i,temp,dat1,dat2;RST1=0;SCLK=0;RST1=1;for(i=8;i>0;i--) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}for(i=8;i>0;i--) //读取数据{ACC_7=IO;SCLK=1;ACC>>=1;SCLK=0;}RST1=0;dat1=ACC;dat2=dat1/16;dat1=dat1%16;dat1=dat1+dat2*10;return(dat1);}/////////============向DS1302写入数据程序================//////////// void write1302(uchar add,uchar dat){uchar i,temp;RST1=0;SCLK=0;RST1=1;for(i=0;i<8;i++) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}temp=(dat/10<<4)|(dat%10);for(i=0;i<8;i++) //发送数据{SCLK=0;IO=(bit)(temp&0x01);temp>>=1;SCLK=1;}RST1=0;}/////////-------------获取DS1302的时间-----------////////void ds1302(){uchar i,add=0x81;write1302(0x8e,0x00); //允许向DS1302写入数据for(i=0;i<7;i++){tab_1302[i]=read1302(add); //获得的数据已转换为十进制add+=2;}write1302(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠}///////////============转换函数============///////////void change(){tab_time[0]=tab_1302[2]/10; //小时十位tab_time[1]=tab_1302[2]%10; //小时个位tab_time[3]=tab_1302[1]/10; //分十位tab_time[4]=tab_1302[1]%10; //分个位tab_time[6]=tab_1302[0]/10; //秒十位tab_time[7]=tab_1302[0]%10; //秒个位tab_day[0]=tab_1302[6]/10; //年十位tab_day[1]=tab_1302[6]%10; //年个位tab_day[3]=tab_1302[4]/10; //月十位tab_day[4]=tab_1302[4]%10; //月个位tab_day[6]=tab_1302[3]/10; //日十位tab_day[7]=tab_1302[3]%10; //日个位}////////////========主函数=======///////////// void main(){P2M0=0xff;P2M1=0;ds1302_init();int0_init();while(1){ds1302();change();display_time();while(!k4){ds1302();change();display_day();}}}/////========time=========////////////void int0() interrupt 0{uchar ky=0,n1,n2,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[0];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1>=60)n1=0;}}tab_1302[0]=n1;change();P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[1];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2>=60)n2=0;}}tab_1302[1]=n2;change();P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[2];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==24)n3=1;}}tab_1302[2]=n3;change();P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}//////===4====////if(ky==4){flag=0;ds1302_init();}}}/////////////=============day================///////////// void int1() interrupt 2{uchar ky=0,n1,n2=1,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[6];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1==50)n1=0;}}tab_1302[6]=n1;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[4];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2==13)n2=1;}}tab_1302[4]=n2;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[3];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==31)n3=1;}}tab_1302[3]=n3;change();P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}if(ky==4){flag=0;ds1302_init();}}}。
基于单片机的多功能电子万年历设计引言在现代社会中,计算机及其应用已经成为我们生活中不可或缺的一部分。
计算机科技的发展不仅使我们的生活更加便捷,还为我们提供了更多的娱乐和功能选择。
在这样一个科技高度发达的时代,电子万年历作为一种基于单片机技术的应用产品,正逐渐走进人们的生活。
而本文将着重对基于单片机的多功能电子万年历进行设计与实现。
一、设计目标本次设计主要是基于单片机的多功能电子万年历。
设计目标包括:1.显示日期、时间和星期几的功能。
2.具备日历计算功能,能够计算今天是该年的第几天,该周的第几天等信息。
3.具备闹钟和定时器功能。
二、设计思路基于单片机的多功能电子万年历的设计理念是通过单片机与LCD显示屏、温度传感器、按键等外设组合实现多种功能。
具体实现步骤如下:1. 使用单片机和RTC(Real-Time Clock)芯片实现时间的获取和处理。
RTC芯片可以提供准确的时钟信息,单片机可以通过与RTC芯片的通信来读取时钟信息,并进行相应的处理。
2.使用单片机与LCD显示屏进行通信,将获取的时间、日期和星期信息显示在LCD显示屏上。
3.设计按键接口,通过按键的触发实现切换功能或进行相应操作。
例如,通过按键的触发可以实现日期、时间的调整,以及闹钟和定时器的设置等。
4.使用单片机和温度传感器实现温度测量功能。
通过温度传感器读取当前温度信息,并将其显示在LCD屏幕上。
5.使用定时器功能实现闹钟和定时器的功能。
单片机可以通过定时器来控制闹钟和定时器的开启与关闭,并通过LCD屏幕上的显示提醒用户。
三、电路设计本次设计中需要使用的元器件主要包括单片机、RTC芯片、LCD显示屏、温度传感器和按键。
其中,单片机为本次设计的核心控制器,RTC芯片用于提供准确的时钟信息,LCD显示屏用于显示时间、日期和其他信息,温度传感器用于测量当前温度信息,按键用于触发相应的操作。
四、软件设计本次设计中需要编写相应的软件程序,用于读取RTC芯片提供的时钟信息,并将其显示在LCD屏幕上。
摘要摘要随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒信息,还具有时间校准等功能。
本设计以数字集成电路技术为基础,单片机技术为核心。
软件设计采用模块化结构,C语言编程。
系统通过LCD显示数据,可以显示公历日期(年、月、日、时、分、秒)以及星期。
在内容安排上首先描述系统硬件工作原理,着重介绍了各硬件接口技术和各个接口模块;其次,详细的阐述了程序的各个模块和实现过程。
具体实现功能:(1)显示年月日时分秒及星期信息(2)具有可调整日期和时间功能关键词:万年历单片机DS1302目录目录摘要 (I)第一章方案论证 (1)1.1单片机芯片的选择方案和论证 (1)1.2显示模块选择方案和论证 (1)1.3时钟芯片的选择方案和论证 (1)1.4电路设计最终方案决定 (2)第二章系统的硬件设计与实现 (3)2.1 总体电路 (3)2.2单片机主控制模块的设计 (3)2.2.1 AT89S52的介绍 (3)2.2.2 单片机主控制模块介绍 (5)2.3 时钟模块设计 (5)2.3.1 DS1302的性能特性 (5)2.3.2 DS1302数据操作原理 (6)2.3.3 DS1302与AT89S52接口电路设计 (7)2.4显示模块的设计 (8)2.4.1 LCM1602介绍 (8)2.4.2 LCM1602与单片机的接口 (9)第三章系统的软件设计 (11)3.1程序总体描述 (11)3.2模块程序描述 (11)第四章PROTEUS仿真 (13)4.1 PROTEUS工作界面 (13)4.2 PROTEUS功能仿真 (13)第五章测试与结果分析 (15)5.1测试仪器 (15)5.2硬件测试 (15)5.3软件测试 (16)5.4 测试结果分析与结论 (16)5.4.1 测试结果分析 (16)5.4.2 测试结论 (16)第六章总结与展望 (17)致谢 (19)参考文献 (21)附录1 系统电路图 (23)附录2 系统程序 (24)第一章方案论证第一章方案论证1.1单片机芯片的选择方案和论证方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。
基于STCC单片机的多功能电子万年历————————————————————————————————作者:————————————————————————————————日期:摘要本文介绍了基于STC89C52单片机的多功能电子万年历的硬件结构和软硬件设计方法。
本设计由数据显示模块、温度采集模块、时间处理模块和调整设置模块四个模块组成。
系统以STC89C52单片机为控制器,以串行时钟日历芯片DS1302记录日历和时间,它可以对年、月、日、时、分、秒进行计时,还具有闰年补偿等多种功能。
温度采集选用DS18B20芯片,万年历采用直观的数字显示,数据显示采用1602A液晶显示模块,可以在LCD上同时显示年、月、日、周日、时、分、秒,还具有时间校准等功能。
此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,具有广阔的市场前景。
关键字:万年历温度计液晶显示ABSTRACTThis paper introduces the based on STC89C52 multi-function electronic calendar of the hardware structure and software and hardware design method. This design by data display module, temperature acquisition module, time processing module and set module four modules. With STC89C52 single-chip microcomputer system for the controller to serial clock calendar chip DS1302 record calendar and time, it can be to date and time, minutes and seconds for the time, also has a leap year compensation and other functions. Temperature gathering choose DS18B20 chip, calendar by using object digital display, data showed that the 1602 A liquid crystal display module, can be in the LCD shows at the same time year, month, day, Sunday, when, minutes and seconds, still have time calibration etc. Function. This calendar has read the convenient, direct display, functional diversity, simple circuit, low cost, and many other advantages, has a broad market prospect.Key words:Perpetual Calendar thermometer LCD display目录摘要 (III)ABSTRACT (IV)前言 (VI)1 绪论 01.1 课题研究的背景 01.2课题的研究目的与意义 01.3课题解决的主要内容 02 系统的方案设计与论证 (1)2.1单片机芯片设计与论证 (2)2.2按键控制模块设计与论证 (2)2.3时钟模块设计与论证 (2)2.4温度采集模块设计与论证 (3)2.5显示模块模块设计与论证 (3)3 系统硬件的设计 (4)3.1 STC89C52单片机 (4)3.2时钟芯片DS1302接口设计与性能分析 (7)3.3温度芯片DS18B20接口设计与性能分析 (11)3.4 LCD显示模块 (16)3.5按键模块设计 (17)3.6复位电路的设计 (18)4 系统的软件设计 (20)4.1主程序流程图的设计 (20)4.2 程序设计 (21)5 系统的机体设计 (27)5.1系统的模块组成 (27)5.2 功能实现 (27)结论 (29)参考文献 (30)致谢 (31)附录 (32)前言随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
基于单片机的电子时钟的设计与实现电子时钟是一种使用微处理器或单片机作为主控制器的数字时钟。
它不仅能够显示当前时间,还可以具备其他附加功能,如闹钟、日历、温度显示等。
一、设计目标设计一个基于单片机的电子时钟,实现以下功能:1.显示时间:小时、分钟和秒钟的显示,采用7段LED数码管来显示。
2.闹钟功能:设置闹钟时间,到达设定的时间时会发出提示音。
3.日历功能:显示日期、星期和月份。
4.温度显示:通过温度传感器获取当前环境温度,并显示在LED数码管上。
5.键盘输入和控制:通过外部键盘进行时间、日期、闹钟、温度等参数的设置和调整。
二、硬件设计1.单片机选择:选择一款适合的单片机作为主控制器,应具备足够的输入/输出引脚、中断和定时器等功能,如STC89C522.时钟电路:使用晶振为单片机提供稳定的时钟源。
3.7段LED数码管:选择合适的尺寸和颜色的数码管,用于显示小时、分钟和秒钟。
4.温度传感器:选择一款适合的温度传感器,如DS18B20,用于获取环境温度。
5.喇叭:用于发出闹钟提示音。
6.外部键盘:选择一款适合的键盘,用于设置和调整时间、日期、闹钟等参数。
三、软件设计1.初始化:设置单片机定时器、外部中断和其他必要的配置。
2.时间显示:通过定时器中断,更新时间,并将小时、分钟和秒钟分别显示在相应的LED数码管上。
3.闹钟功能:设置闹钟时间,定时器中断检测当前时间是否与闹钟时间一致,若一致则触发警报。
4.日历功能:使用定时器中断,更新日期、星期和月份,并将其显示在LED数码管上。
5.温度显示:通过定时器中断,读取温度传感器的数据,并将温度显示在LED数码管上。
6.键盘输入和控制:通过外部中断,读取键盘输入,并根据输入进行相应的操作,如设置时间、闹钟、日期等。
7.警报控制:根据设置的闹钟时间,触发警报功能,同时根据用户的设置进行控制。
四、测试与调试完成软件设计后,进行系统测试与调试,包括验证显示时间、日期、温度等功能的准确性,以及闹钟和警报功能的触发与控制。
单片机课程设计报告万年历的设计基于51单片机的万年历摘要:电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
万年历的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89C52单片机,LCD显示电路,以及调时按键电路等组成。
在单片机的选择上本人使用了AT89C52单片机,该单片机适合于许多较为复杂控制应用场合。
显示器使用了1602液晶显示,并且使用蜂鸣器实现了整点报警的功能,温度测试的功能实现使用了DS18B20,并实现了温度过高或过低时的温度报警。
软件方面主要包括日历程序、时间调整程序,显示程序等。
程序采用C语言编写。
所有程序编写完成后,在KeilC51软件中进行调试,确定没有问题后,在Proteus软件中嵌入单片机内进行仿真,并最终实现基本要求。
综上所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
一、设计要求基本要求:1,8 个数码管上显示,显示时间的格式为(假如当前时间是19:32:20)“19-32-20”;2,具有日历功能;③时间可以通过按键调整。
发挥部分:④具有闹钟功能(可以设定多个)。
二:总体设计电路设计框图系统硬件概述本电路是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;时钟电路由单片机定时功能提供;温度的采集由DS18B20构成,它具有独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯,使用时不需要额外的外围电路。
目录一、设计任务二、设计方案三、硬件及电路设计四、程序设计及流程图五、设计体会一、设计任务利用单片机及外围接口电路(键盘接口和显示接口电路)设计制作一个电子日历时钟系统。
使用液晶显示器将日期,时间实时显示出来,并且能够通过按钮修改日期,完成实时操作并具有闹铃功能。
二、设计方案硬件选择:单片机AT89C51,DS1302时钟芯片,SED1520液晶控制器接口芯片:74LS138,74LS373,片选CS0三、硬件及电路设计(一)实验所用芯片简要介绍1、主控芯片采用单片机AT89C51AT89C51是一种带4K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称单片机,与AT80C51引脚和指令系统完全兼容,可擦除只读存储器可以反复擦除1000次。
AT89C51共有128×8位内部RAM ,32可编程I/O线,两个16位定时器/计数器,5个中断源,采用全静态工作,三级程序存储器锁定和可编程串行通道,工作频率为0Hz-24MHz。
另外片内内置振荡器和时钟电路,低功耗的闲置和掉电模式。
2、实时时钟部分采用DS1302DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM 的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为 2.5V~5.5V。
采用三线接口与CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
3、SED1520液晶控制器SED1520液晶显示驱动器是一种点阵图形式液晶显示驱动器,它可直接与8位微处理器相连,集行、列驱动器于一体,因此使用起来十分方便,作为内藏式控制器被广泛应用于点阵数较少的液晶显示模块,内置显示RAM区RAM容量为2560位,RAM中的1位数据控制液晶屏上一个点的亮灭状态:“1”表示亮,“0”表示暗,具有16个行驱动口和16个列驱动口,可直接与80系列微处理器相连,亦可直接与68系列微处理器相连。
毕业论文(设计)基于单片机进行实时日历和时钟显示设计学生姓名:指导教师:合作指导教师:专业名称:自动化所在学院:2012年6月目录摘要 (Ⅰ)Abstract (Ⅱ)第一章前言 (1)第二章设计方案论证 (2)2.1功能要求 (2)2.2方案确定 (2)第三章主控制器和外围器件 (4)3.1AT89S52单片机 (4)3.2DS1302时钟芯片 (4)3.3数码管LED (7)3.4译码器74HC138 (8)3.5锁存器74LS244 (8)第四章硬件设计 (9)4.1电路设计框图 (9)4.2系统概述 (9)4.3电源设计 (9)4.5单片机系统的晶振电路 (10)4.6主电路设计 (11)第五章软件设计 (12)5.1主程序设计 (12)5.2键盘子程序设计 (13)5.3日历时钟子程序设计 (15)5.4显示子程序设计 (17)第六章系统调试 (18)6.1软件调试 (18)6.2硬件调试 (19)第七章结论 (20)致谢 (21)参考文献 (22)附录 (26)附录Ⅰ硬件电路图 (26)附录Ⅱ主程序源代码 (27)摘要本设计是基于51系列的单片机进行的实时日历和时钟显示设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
实时日历和时钟显示的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89S52单片机,通过LED显示数据,所以具有人性化的操作和直观的显示效果。
软件方面主要包括时钟程序、键盘程序,显示程序等。
本系统以单片机的汇编语言进行软件设计,为了便于扩展和更改,软件的设计采用模块化结构,使程序设计的逻辑关系更加简洁明了,以便更简单地实现调整时间及日期显示功能。
所有程序编写完成后,在wave软件中进行调试,成功运行后,在Protel软件中进行仿真并调试。
关键词:AT89S52, DS1302, LEDAbstractThis design is based on 51 series monolithic integrated circuits of a real-time calendar and the clock shows the design , you can show how and when a week , has may adjust the date and time functions . in the design for monolithic integrated circuits , and peripheral to expand the basic theories of knowledge was fairly comprehensive preparation .Real-time calendar and the clock shows the design in hardware and software design of hardware that is synchronized the led display at89s52 monolithic integrated circuits, and when should the electrical circuits, the system through the led display data so be humanized operate and intuitive that effect. Including the software application programs, the keyboard, the program, etc. This system to monolithic integrated circuits of the assembly language for easily developing software design, and changes, software design to use modular design, the programming logical relationship with more and more so as to realize the time and date display the functions. all procedures in writing after wave of debugging the software and make no question of the proteus software embedded monolithic integrated circuits.Key words:AT89S52, DS1302, LED第一章前言在日新月异的21世纪里,家用电子产品得到了迅速发展。
XX 学院毕业设计(论文)题目:基于单片机的电子万年历设计院系:电子工程学院专业:电子科学与技术班级:学生姓名:导师姓名:职称:教授起止时间:2010年03月09日至 2010年06月20日毕业设计(论文)任务书学生姓名指导教师职称教授院系电子工程学院专业电子科学与技术题目基于单片机的电子万年历设计任务与要求一、任务:设计基于单片机的电子万年历,达到同时显示年、月、日、时、分、秒的要求。
利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。
同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。
二、要求:1、熟悉单片机,C语言等相关知识。
2、学会使用Keil C软件开发环境。
3、定时器整体硬件设计,中断系统设计,软件编程,系统调试等。
4、能自己独立解决设计中的问题,加强自主学习能力。
5、成果形式:软件程序,硬件模块,论文。
毕业设计 (论文) 工作计划学生姓名____ 指导教师___职称教授_院别_____电子工程学院_______专业电子科学与技术__________ 题目基于单片机的电子万年历设计工作进程主要参考书目(资料)1、 单片机原理及应用2、单片机原理及接口技术3、 单片机编程实例4、单片机实验教程 相关网站: 1、计算机及配套软件2、单片机3、元件若干除每周定时具体指导外,学生有问题也可随时联系指导。
如有特殊原因可适当调整,否则按计划执行。
主要参考书目(资料) 主要仪器设备及材料 论文(设计)过程中教师的指导安排对计划的说明XX学院毕业设计(论文)开题报告电子工程学院电子科学与技术专业级班课题名称:基于单片机的电子万年历设计学生姓名:学号:0 0指导教师:报告日期: 2010年3月15号1.本课题所涉及的问题及应用现状综述在当代繁忙的工作与生活中,时间与我们每一个人都有非常密切的关系,每个人都受到时间的影响。
为了更好的利用我们自己的时间,我们必须对时间有一个度量,因此产生了钟表。
基于单片机的电子万年历的设计摘要本文以AT89C2051单片机为主控芯片,采用美国DALLAS公司的涓细充电时钟芯片DS1302为时钟控制芯片,设计了一个电子万年历,能够显示年、月、日、时、分、秒、星期信息。
关键词实时显示 AT89C2051 单片机目录0、引言 (3)1、电子万年历的硬件电路设计 (3)2、主控制器AT89C2051 (3)3、DSl302时钟芯片的工作原理 (4)3.1 引脚功能 (4)3.2 DSl302的控制字节 (4)3.3 DSl302的复位特征和时钟控制要求 (4)3.4 数据输入输出I/O (5)3.5 DSl302的寄存器 (5)4、DS1302与微控制器的连接及软件控制 (5)4.1 DSl302与AT89C2051的连接 (5)4.2 软件控制 (6)4.3 根据在调试中出现的问题,作如下说明: (9)5、总结 (9)0、引言日常生活生产中有许多地方需要电子时钟和日历,比如家庭,办公室,以及一些智能化仪表。
目前的电子时钟日历系统多采用时钟芯片以简化系统的设计。
DSl302是众多时钟芯片中一款性价比较高的产品。
以AT89C2051单片机为主控芯片,采用美国DALLAS 公司的实时时钟芯片DSl302为时钟控制芯片,设计并实现的各种时钟控制电路,应用于各种家电、实验设备等。
其能够显示年、月、日、时、分、秒、星期。
并且可根据需要对各个位进行调节。
1、电子万年历的硬件电路设计硬件电路设计是电子时钟日历系统设计的第一步。
系统由主控模块,时钟芯片。
显示电路、键盘扫描电路共四个部分组成,电路构成,框图如图l所示。
图l 电子万年历系统的框架图主控芯片使用MCU-51系列的AT89C2051单片机,时钟芯片使用美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟DSl302。
采用DSl302作为主要计时芯片,可以作到计时准确。
更重要的是,DSl302可以在很小的后备电源(2.5-5.5V电源,在2.5V 时耗电小于300Na)下继续计时,并可编程选择多种充电电源来对后备电源进行慢速充电,可以保证后备电源基本不耗电。
题目:基于单片机的电子万年历设计基于单片机的万年历设计摘要随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
目前,单片机技术的应用产品已经走进了千家万户。
电子万年历的出现给人们的生活带来了诸多方便。
本设计是一个基于AT89S52单片机的日历显示系统,本设计能显示公历年、月、日,以及时、分、秒、温度、星期等信息,而且还提供了农历信息,具有调整时间,温度采集,闹钟及个性化的闹铃等功能。
系统所用的时钟日历芯片DS1302具有高性能、低功耗、接口简单的特点,使本系统电路简化,编程方便,同时功能也很强。
采用AT89S52单片机的万年历系统可以很好的改善传统采用模拟电路引起的计时不准确,不可靠,一致性差等问题。
此系统计时精确,价格低廉,可以广泛应用在生活,学习和工作等任何领域,并且起到重要作用。
关键词:万年历;单片机;时钟芯片;温度芯片;公历转农历The Design of Electronic Calendar clock Based on Single-chipMicrocomputerAbstractAlong with the technical fast development, time passing, to from the view sun, the pendulum clock to the present electron clock, the humanity studies unceasingly, innovates unceasingly the record. At present, the monolithic integrated circuit technology's application product already entered everyone. The electronic ten thousand calendar's appearances have brought conveniently many for people's life.This design is one based on AT89S52 single-chip microcomputer calendar display system, it can demonstrate years, the month, the date of the Gregorian calendar, and hour, minute, second, temperature, week and so on. Moreover it has also provided the lunar calendar information, adjustable time pattern, temperature sample, alarm system, individual quarter-bell and so on. The system clock calendar DS1302 with high performance, low power consumption and simple interface features Circuit enable the system to streamline programming convenience, but also highly functional. The problems of inaccurate, unreliable, and the uniform inferior can be come up when you use the analogous circuit. However, it can be improved when you use the clock system based on AT89S52 single-chip microcomputer. The system time accurate, low cost and can be widely applied to the life, study and work in any field, and has played an important role.Key words:The Electronic Calendar Clock;Single-chip Microcomputer;The Time Calendar Clock;Temperature Chip;The Lunar Calendar Convert To The Gregorian Calendar目录摘要 (I)Abstract (II)第一章引言 (1)1.1 概述 (1)1.2 单片机的简介 (1)第二章方案设计与论证 (4)2.1 单片机芯片设计与论证 (4)2.2 电源模块设计与论证 (5)2.3 按键控制模块设计与论证 (5)2.4 时钟模块设计与论证 (5)2.5 温度采集模块设计与论证 (5)2.6 显示模块模块设计与论证 (6)第三章系统的硬件设计 (7)3.1 主控芯片AT89S52与最小外围系统 (7)3.1.1 AT89S52的概述 (7)3.1.2 AT89S52最小系统的设计 (10)3.2 时钟芯片DS1302接口设计与性能分析 (11)3.2.1 DS1302性能简介 (11)3.2.2 DS1302接口电路设计 (12)3.3 温度芯片DS18B20接口设计与性能分析 (14)3.3.1 DS18B20性能简介 (14)3.3.2 DS18B20接口电路设计 (15)3.3.3 DS18B20的工作时序 (16)3.4 闹钟模块接口设计与性能分析 (17)3.4.1 AT24C02器件使用 (17)3.4.2 接口电路设计 (19)3.5 LCD显示模块 (19)3.5.1 LCM1602的特性及使用说明 (19)3.5.2 LCM1602与MCU的接口电路 (21)3.6 按键模块设计 (21)第四章软件设计 (23)4.1 软件总体部分的设计 (23)4.2 LCD驱动及液晶显示 (24)4.3 按键识别及处理 (25)4.4 温度数据采集 (26)4.5 时间数据采集 (27)4.6 闹钟程序 (28)4.7 公历转农历的实现 (28)第五章系统的调试 (30)总结 (31)参考文献 (32)附录A 设计原理图 (33)附录B 源程序 (34)附录C 公历对应的农历数据表 (55)致谢 (58)第一章引言1.1 概述随着电子技术的发展,人类不断研究,不断创新纪录。
微机原理课程设计报告题目:电子日历时钟学院电子与信息学院专业08信息工程1班组员陈晓伟05 冯劲增06 指导教师林耀荣提交日期2010.6.21一课程设计题目:电子日历时钟二实现的功能:基本功能:(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. 主程序八、性能测试与故障排查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_STA TE,#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_STA TEJZ SCAN_HOUR ;闹钟开关已打开?MOV A,NHOUR_BCDCJNE A,HOUR_BCD,W AITMOV A,NMINUTE_BCDCJNE A,MINUTE_BCD,W AITALARM: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: M OV 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 tableMOV 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_STA TE ;是否显示闹钟状态位?(最末位小数点)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 overflowRRC AA04: 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: C JNE A,#03H,B04B03: M OV A,TICK_CNT ; take times of overflowRRC AJNC B05 ; check bit C ( 1 or 0 )B04: M OV P1,#0efH ; turn on DS5B05: L CALL 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: C JNE A,#02H,C04C03: M OV A,TICK_CNT ; take times of overflowRRC AJNC C05 ; check bit C ( 1 or 0 )C04: M OV P1,#0f7H ; turn on DS4C05: L CALL 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 AD04: 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 overflowRRC 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 overflowRRC 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/timePUSH 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/flashADH: 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: L JMP 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 ;是否进入日期调整01JYY: 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" monthMOV A,DAY_BCD ; take BCD of "day"CJNE A,#30H,D0A ; is up to 30 days ?DD1: MOV DAY_BCD,#01H ; keep the first dayLJMP 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_FLAG PUSH 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_STA TECPL A ;取非ANL A,#01H ;保留最后MOV ALAM_STA TE,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号闪烁中MOV FLASH_FLAG,#02H ; 设置3,4号闪烁SJMP EX1_RETED2: CJNE A,#02H,ED3 ; "02" 3,4号闪烁MOV FLASH_FLAG,#03H ; 设置5,6号闪烁SJMP EX1_RETED3: MOV FLASH_FLAG,#00H ; 关闭所有闪烁EX1_RET:NOPPOP PSWPOP ACCRETI;------------------------------------; ---------------------------------------------; 带显示延迟D_CNT_DIS EQU 2AHDIS_DELAY: MOV D_CNT_DIS,#10H ; or(#0BH)DELAY_LOOP: LCALL DISPLAY ; with LED display DJNZ D_CNT_DIS,DELAY_LOOPRET; -----------------------------------------------; ----------------------------------------------------------; sub: BCD division; BCD除法:除4; 输出:; R3: 余数; R2: 商BCD_DIV4: MOV R0,YEAR_BCD ; dividend in BCD MOV R1,#04H ; divider in BCDMOV R2,#00H ; R2:输出商MOV A,R1CPL AADD A,#9BHMOV R1,A ; R1:BCD补码MOV A,R0ANL A,#0F0H ; BCD高位SWAP ALP0: M OV R3,A ; BCD码的余数ADD A,R1DA AJNC LP1INC R2SJMP LP0LP1: M OV A,R3SWAP AMOV R3,AMOV A,R2SWAP AMOV R2,A ; 商的高位MOV A,R0ANL A,#0FH ; 年BCD的低位ORL A,R3LP2: M OV R3,AADD A,R1DA AJNC LP3INC R2SJMP LP2LP3: N OP ; no roundingRET;----------------------------------------------; ------------------------------------------------------ TAB:DB 0c0H ; for "0"DB 0f9H ; for "1"DB 0a4H ; for "2"DB 0b0H ; for "3"DB 99H ; for "4"DB 92H ; for "5"DB 82H ; for "6"DB 0f8H ; for "7"DB 80H ; for "8"DB 90H ; for "9"TAB2:DB 0C0H ; "0"DB 11001000B ; "N"DB 10001110B ; "F"DB 0FFH ; " "DB 40H ; "0."DB 07FH ; "."DB 00001110B ; "F."END。