基于单片机和DS1302电子万年历的设计
基于单片机和DS1302的电子万年历设计报告

基于单片机和DS1302的电子万年历设计报告一、设计意义随着科技的不断进步和发展,单片机的使用已经渗透到我们日常生活当中的各个领域,几乎很难找到有哪个领域没有使用单片机的踪迹。
导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,以及程控玩具、电子宠物等等,这些都离不开单片机,更不用说自动控制领域的机器人、智能仪表、医疗器械了。
本文设计的电子万年历属于小型智能家用电子产品。
利用单片机进行控制,实时时钟芯片进行记时,外加掉电存储电路和显示电路,可实现时间的调整和显示。
电子万年历既可广泛应用于家庭,也可应用于银行、邮电、宾馆、饭店、企业、商店等相关行业的大厅,以及单位会议室、门卫等场所。
因而,此设计具有相当重要的现实意义和实用价值。
二、设计方案本设计以AT89S52单片机为核心,构成单片机控制电路,结合DS1302时钟芯片和24C02 FLASH存储器,显示阳历的年、月、日、星期、时、分、秒和阴历的年、月、日,在显示阴历时间时,能标明是否闰月,同时完成对它们的自动调整和掉电保护,全部信息用液晶显示出来。
输入接口由三个按键来实现,用这三个按键可以对日期和时间进行调整,并可以对闹铃的开关和闹铃的时间进行设置。
闹铃功能通过蜂鸣器来实现。
软件控制程序实现所有的功能。
整机电路使用+5V稳压电源,可稳定工作。
系统框图如图2-1所示,其软硬件设计简单,时间记录准确,可广泛应用于长时间连续显示的系统中。
三、硬件电路设计按照系统设计功能的要求,初步确定设计系统由主控模块、时钟模块、存储模块、键盘接口模块、显示模块和闹铃模块共6个模块组成,电路系统构成框图如图3-1所示。
主控芯片使用52系列AT89S52单片机,时钟芯片使用美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟芯片DS1302,存储模块采用美国ATMEL公司生产的低功耗CMOS串行EEPROM存储芯片AT24C02。
基于51单片机DS1302万年历课程设计报告

基于51单片机DS1302万年历课程设计报告课程名称:微机原理课程设计题目:基于DS1302芯片万年历摘要DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM,通过简单的串行接口与单片机进行通信实时时钟/日历电路.提供秒、分、时、日、日期.、月、年的信息,每月的天数和闰年的天数可自动调整时钟。
本次课程设计的是使用专门的时钟芯片DS1302在数码管上显示的数字电子钟,并能通过按键对其进行调时和校准以及实现年月日。
DS1302是一种高性能、低功耗、带RAM的实时时钟芯片,它能够对时,分,秒进行精确计时,它与单片机的接口使用同步串行通信,仅用3条线与之相连接,就可以实现STC-51单片机对其进行读写操作,把读出的时间数据送到数码管上显示。
程序运行时,数码管将从当前时间开始显示,通过调节K2键和K3键可以分别对小时和分钟进行调整,调整后,时钟以新的时间为起点继续刷新显示,通过调节K1键可以切换年月日和时钟显示。
关键字:STC-51单片机,DS1302,数码管,动态扫描,调时,切换,秒闪;目录一、设计任务与要求 (4)1.1设计任务 (4)1.2设计要求 (4)1.3发挥部分 (4)1.4创新部分 (4)二、方案总体设计 (5)2.1设计目的 (5)2.2硬件功能描述 (5)2.3设计方案选择 (5)2.4总体设计 (6)2.5总体方案及基本工作原理 (6)三、硬件设计 (7)3.1 STC89C51芯片 (7)3.2电源模块及晶振模块 (7)3.3 DS1302 (8)3.4数码管显示模块 (9)3.5蜂鸣器部分 (10)3.6按键部分 (11)四、软件设计 (13)4.1软件流程图 (13)4.2 软件设计 (13)主函数部分: (13)五、系统仿真和调试 (15)5.1 仿真软件简介 (15)5.2硬件调试 (15)5.3软件调试 (15)5.4使用说明 (16)六、设计总结与体会 (18)6.1学习方面 (18)6.2工作方面 (18)七、参考文献 (19)一、设计任务与要求1.1设计任务DS1302万年历;1.2设计要求利用DS1302生成万年历,时钟可调,通过四位数码管显示,并可实现秒闪功能,同时蜂鸣器闹铃;1.3发挥部分设置按键K3用来切换显示时钟和年月日;1.4创新部分只设置了两个按键K1和K2来调节时分,时钟到24归零,分钟到60归零,分钟有长按迅速调节功能。
基于89C52单片机和DS1302的万年历设计

基于89C52单片机和DS1302的万年历设计摘要古人依靠日冕、漏刻记录时间,而随着现代科技的发展,电子万年历已经成为日渐流行的日常计时工具。
本文研究的万年历系统拟用STC89C52单片机控制,以DS1302时钟芯片计时、1602液晶屏显示。
系统主要由单片机控制电路,显示电路以及校正电路三个模块组成。
本文阐述了系统的硬件工作原理,所应用的各个接口模块的功能以及其工作过程,论证了设计方案理论的可行性。
系统程序采用C语言编写,经Keil软件进行调试后在Proteus软件中进行仿真测试,可以显示年、月、日、星期、时、分、秒,并具有校准功能和与即时时间同步的功能。
实验结果表明此万年历实现后具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
关键词:万年历单片机DS1302 lcd1602目录第一章前言............................................................................................. 错误!未定义书签。
1.1引言(课题研究的意义) (1)1.2本课题主要的研究工作 (1)1.2.1研究内容 (1)1.2.2论文章节安排 (2)1.3本章小结 (2)第二章单片机的概述 (3)2.1单片机的定义和特点 (3)2.1.1单片机的定义 (3)2.1.2单片机的特点 (3)2.2单片机的发展现状和趋势 (3)2.3编程语言的选择 (4)2.4本章小结 (4)第三章设计要求和方案论证 (5)3.1设计要求 (5)3.2单片机芯片的选择方案和论证 (5)3.3显示模块选择方案和论证 (5)3.4时钟芯片的选择方案和论证 (6)3.5电路设计最终方案决定 (6)3.6本章小结 (6)第四章系统的硬件设计与实现 (7)4.1电路设计框图 (7)4.2系统硬件概述 (7)4.3主要单元电路的设计 (7)4.3.1 STC89C52单片机简介 (7)4.3.2单片机主控制模块的设计 (10)4.3.3时钟电路模块的设计 (11)4.3.4独立式键盘设计 (13)4.3.5显示模块的设计 (13)4.4本章小结 (15)第五章系统的软件设计 (16)5.1程序流程图 (16)5.1.1系统总流程图 (16)5.1.2时钟程序流程图 (16)5.1.3液晶显示程序流程图 (17)5.2程序的设计 (18)5.2.1读写DS1302程序 (18)5.2.2液晶显示程序 (19)5.3本章小结 (19)第六章结束语 (20)致谢词 (21)参考文献 (22)附录一:系统电路图 (23)附录二:系统程序 (24)第一章前言1.1引言(课题研究的意义)万年历是我国古代传说中最古老的一部太阳历。
基于DS1302时钟芯片的电子万年历设计

基于DS1302时钟芯片的电子万年历设计【摘要】本文阐述了一种基于DS1302时钟芯片的电子万年历软硬件设计方法。
绘制了电路图,并给出了该电子万年历的部分C语言源代码。
【关键词】DS1302;时钟芯片;单片机0.引言时钟芯片被广泛应用于需要时间信息的电路设计领域中。
当今市场上的时钟芯片种类繁多,比如DS1302、DS12C887、PCF8485、SB2068等。
其中DS1302具有价格低、功耗小、易操作等优点,故本文选用DS1302作为本次设计的时钟芯片。
1.电路连接电路连接图如图1所示,主要包括STC89C52单片机、DS1302、12864液晶屏和3个独立按键等电子元器件。
1.1 DS1302简介及其与单片机的接口电路DS1302是DALLAS公司推出的涓流充电时钟芯片,可提供秒、分、时、日、月、年、周等时间信息,通过串行接口与单片机进行通信,并且仅需用到3个口线,功率小于1mW,被广泛应用于便携式仪器及其他电池供电的仪器仪表。
下面阐述DS1302的电路连接问题:DS1302一共有8个管脚,其中第1脚接5V电源,4脚接地;2脚和3脚跨接一个32.768KHz的无源晶振,该晶振作为DS1302的正常工作提供时钟脉冲;8脚为外部备用电源输入端,本文使用一个3.3V的纽扣电池作为备用电源,当系统掉电后,备用电源立即给DS1302供电,可以避免DS1302内部时间信息的丢失;5脚、6脚、7脚为DS1302的3个控制端,分别接至单片机的P3.7、P3.6、P3.5口,5脚REST为复位端,低电平有效,6脚I/O为数据输入输出口,7脚CLK为串行时钟信号输入端,该时钟信号由单片机提供。
1.2 独立按键接口电路本文在设计时使用到了3个独立按键,其一端共同接地,另外一端分别接至单片机P1.0、P1.1、P1.2。
当按键被按下时,对应的单片机端口将出现低电平,单片机通过判断该低电平信号来获知相应按键被按下,本文通过这3个按键来设定时间。
电子万年历设计(基于AT89C51单片机和DS1302时钟芯片)1.doc

随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业界的第三次革命。
第一次是摆和摆轮游丝的发明,相对稳定的机械振荡频率源使钟表的走时差从分级缩小到秒级,代表性的产品就是带有摆或摆轮游丝的机械钟或表。
第二次革命是石英晶体振荡器的应用,发明了走时精度更高的石英电子钟表,使钟表的走时月差从分级缩小到秒级。
第三次革命就是单片机数码计时技术的应用(电子万年历),使计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!因此,电子万年历的出现带来了钟表计时业界跨跃性的进步……我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,使万年历除了原有的显示时间,日期等基本功能外,还具有闹铃,报警等功能。
商家生产的电子万年历更从质量,价格,实用上考虑,不断的改进电子万年历的设计,使其更加的具有市场。
本设计为软件,硬件相结合的一组设计。
在软件设计过程中,应对硬件部分有相关了解,这样有助于对设计题目的更深了解,有助于软件设计。
基本的要了解一些主要器件的基本功能和作用。
除了采用集成化的时钟芯片外,还有采用MCU的方案,利用AT89系列单片微机制成万年历电路,采用软件和硬件结合的方法,控制LED数码管输出,分别用来显示年、月、日、时、分、秒,其最大特点是:硬件电路简单,安装方便易于实现,软件设计独特,可靠。
AT89C51是由ATMEL 公司推出的一种小型单片机。
95年出现在中国市场。
其主要特点为采用Flash存贮器技术,降低了制造成本,其软件、硬件与MCS-51完全兼容,可以很快被中国广大用户接受。
本文介绍了基于AT89C51单片机设计的电子万年历。
单片机课程设计报告电子万年历

单片机课程设计报告电子万年历单片机课程设计报告:电子万年历一、设计简介在本次单片机课程设计中,我们选择了电子万年历作为设计主题。
电子万年历是一种结合了数字电路、单片机技术和实时时钟(RTC)技术的电子产品,它具有显示年份、月份、星期、日、时、分、秒的功能,还可以根据用户的需求进行定时、闹钟、报时等功能。
二、硬件设计我们采用了基于8051内核的单片机作为主控芯片。
该单片机具有丰富的I/O 端口,适于实现各种复杂的输入输出操作。
此外,它还内置了定时器和中断控制器,可以很方便地实现实时时钟功能。
1.显示模块:为了方便用户查看时间信息,我们选用了LCD显示屏作为显示设备。
LCD屏具有功耗低、体积小、显示内容丰富等优点。
2.实时时钟(RTC)模块:我们采用了常用的DS1302芯片作为实时时钟模块。
该芯片可以提供秒、分、时、日、星期、月、年的信息,而且还有可编程的报警功能。
3.按键模块:为了实现人机交互,我们设计了一组按键。
用户可以通过按键来调整时间、设置闹钟等。
4.电源模块:为了保证系统的稳定工作,我们采用了稳定的5V直流电源。
三、软件设计我们采用了C语言编写程序。
程序主要由以下几个部分组成:1.主程序:主程序主要负责读取RTC模块的时间信息,并控制LCD显示屏显示时间。
同时,主程序还要检测按键输入,根据用户的需求进行相应的操作。
2.RTC驱动程序:为了正确地读取和设置DS1302芯片的时间信息,我们编写了相应的驱动程序。
驱动程序包括初始化和读写寄存器两部分。
3.按键处理程序:按键处理程序用于检测按键输入,并根据按键值执行相应的操作。
比如,用户可以通过按键来增加或减少时间,设置闹钟等。
4.LCD显示程序:LCD显示程序用于控制LCD显示屏的显示内容。
在本设计中,我们使用了点阵字符库,将时间信息以字符的形式显示在LCD屏上。
四、测试与验证为了确保我们的电子万年历设计正确无误,我们进行了以下的测试和验证:1.硬件测试:首先,我们对硬件电路进行了测试,确保每个模块都能正常工作。
基于单片机DS1302的时钟万年历

#include<>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2^1; //1602管脚定义sbit lcden=P2^0;sbit lcdrs=P2^2;sbit key1=P2^3; //闹钟设置键sbit key2=P2^4;sbit key3=P1^5;//功能键定义sbit key4=P1^6;//增大键定义sbit key5=P1^7;//减小键定义uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week; uchar s1num=0,s1num2=0,temp;bit flag;float f_temp;uint i,d;uchar code table2[]={0x20,0x20,0x2e,0x20,0xdf,0x43}; uchar code table[]="20 - - ";uchar code table1[]=" : : ";sbit ds=P1^0;//ds18b20信号线sbit beep=P1^4; //蜂鸣器管脚定义sbit ACC_7 = ACC^7; //位寻址寄存器定义sbit SCLK = P1^2; // DS1302时钟信号sbit DIO= P1^1; // DS1302数据信号sbit CE = P1^3;//地址、数据发送子程序//void delay2(uint ms)// {// uchar t;// while(ms--); for(t=0;t<120;t++);//}// void playmusic()// {// uint i2=0,j2,k2;// while(jiepai[i2]!=0||song[i2]!=0)// {// for(j2=0;j2<jiepai[i2]*20;j2++)// {// beep=~beep;// for(k2=0;k2<song[i2]/3;k2++);// }// delay2(10);// i2++;// }// }void write_1302( uchar addr,uchar dat ){uchar i,temp;CE=0; //CE 引脚为低,数据传送中止 SCLK=0; //清零时钟总线CE = 1; //CE 引脚为高,逻辑控制有效 //发送地址for ( i=8; i>0; i-- ) //循环8次移位{SCLK = 0;temp = addr;DIO = (bit)(temp&0x01); //每次传输低字节 addr >>= 1; //右移一位SCLK = 1;}//发送数据for ( i=8; i>0; i-- ){SCLK = 0;temp = dat;DIO = (bit)(temp&0x01);dat >>= 1;SCLK = 1;}CE = 0;}//数据读取子程序uchar Read1302 ( uchar addr ){unsigned char i,temp,dat1,dat2;CE=0;SCLK=0;CE = 1;//发送地址for ( i=8; i>0; i-- ) //循环8次移位 {SCLK = 0;temp = addr;DIO = (bit)(temp&0x01); //每次传输低字节 addr >>= 1; //右移一位 SCLK = 1;}//读取数据for ( i=8; i>0; i-- ){ACC_7=DIO;SCLK = 1;ACC>>=1;SCLK = 0;}CE=0;dat1=ACC;dat2=dat1/16; //数据进制转换//十六进制转十进制dat1=dat1%16;dat1=dat1+dat2*10;return (dat1);}//初始化 DS1302void Initial(void) //初始化1302 2010年09月30日23点58分56秒星期一{write_1302 (0x8e,0x00); //允许写保护write_1302 (0x80,0x56); //秒位初始化write_1302 (0x82,0x58); //分钟初始化write_1302 (0x84,0x23); //小时初始化write_1302 (0x86,0x30); //日初始化write_1302 (0x88,0x09); //月初始化write_1302 (0x8c,0x10); //年初始化write_1302 (0x8a,0x01); //日期始化write_1302 (0x8e,0x80); //禁止写保护}void delay(uint z)//延时1ms{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com)//1602写命令{lcdrs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//1602写数据{lcdrs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void dsreset(void) //DS18B20,初始化函数{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit tempreadbit(void)//读1位数据函数{uint i;bit dat;ds=0;i++;ds=1;i++;i++;//i++起到延时作用dat=ds;i=8;while(i>0)i--;return(dat);}uchar tempread(void) //读一个字节数据函数{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1);}return(dat);}void tempwritebyte(uchar dat) //向DS18B20写一个字节数据函数{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb)//写1{ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0; //写0i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) //DS18B20开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uint get_temp() //获取温度{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread(); //读高8位b=tempread(); //读低8位temp=b;temp<<=8; //两个字节组合成1个字节temp=temp|a;f_temp=temp*;temp=f_temp*10+;f_temp=f_temp+; //温度在寄存器中为12位,分辨率为^ return temp;}void display(uchar addr,uchar dat){write_com(0x80+0x40+addr);write_data(0x30+dat);delay(5);}void dis_temp(uint t){uchar i;i=t/100;display(10,i);i=t%100/10;display(11,i);i=t%100%10;display(13,i);}void init()//初始化程序{uchar num;flag=1;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<15;num++){write_data(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<8;num++){write_data(table1[num]);delay(5);}write_com(0x80+0x40+10);for(num=0;num<6;num++){write_data(table2[num]);delay(10);}}void di()//蜂鸣器响函数{beep=0;delay(100);beep=1;}void write_sfm(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_nyrz(uchar add,uchar date)//显示年,月,日,周{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);}void display_week(uchar we){write_com(0x80+12);switch(we){case 1: write_data('M');delay(5);write_data('O');delay(5);write_data('N');break;case 2: write_data('T');delay(5);write_data('U');delay(5);write_data('E');break;case 3: write_data('W');delay(5);write_data('E');delay(5);write_data('D');break;case 4: write_data('T');delay(5);write_data('H');delay(5);write_data('U');break;case 5: write_data('F');delay(5);write_data('R');delay(5);write_data('T');break;case 6: write_data('S');delay(5);write_data('A');delay(5);write_data('T');break;case 7: write_data('S');delay(5);write_data('U');delay(5);write_data('N');break;}}void keyscan()//按键设置{if(key3==0)//功能键按下{flag=0;delay(5);if(key3==0){s1num++;while(!key3);di();switch(s1num)//光标闪烁定位{case 1:write_com(0x80+0x40+7);//定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);//定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);//定位到小时的位置write_com(0x0f);break;case 4:write_com(0x80+0x0e);//定位到星期的位置write_com(0x0f);break;case 5:write_com(0x80+0x9);//定位到日的位置write_com(0x0f);break;case 6:write_com(0x80+0x6);//定位到月的位置write_com(0x0f);break;case 7:write_com(0x80+0x3);//定位到年的位置write_com(0x0f);break;case 8: s1num=0;//复位,时钟走write_com(0x0c);flag=1;write_1302 (0x8e,0x00); //允许写保护 write_1302 (0x80,miao); //秒位初始化 write_1302 (0x82,fen); //分钟初始化write_1302 (0x84,shi); //小时初始化 write_1302 (0x86,day); //日初始化write_1302 (0x88,month); //月初始化write_1302 (0x8c,year); //年初始化write_1302 (0x8a,week); //日期始化write_1302 (0x8e,0x80); //禁止写¥break;}}}if(s1num!=0)//只有功能键按下后,增大,增小建才有效{if(key4==0)//增大建{delay(5);if(key4==0){while(!key4);di();switch(s1num){case 1: miao++;if(miao==60)miao=0;write_sfm(6,miao);//write_1302(write_second,miao);write_com(0x80+0x40+7);break;case 2: fen++;if(fen==60)fen=0;write_sfm(3,fen);//write_1302(write_minute,fen);write_com(0x80+0x40+4);break;case 3: shi++;if(shi==24)shi=0;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week++;if(week==8)week=1;display_week(week);write_com(0x80+14);break;case 5: day++;if(day==31)day=1;write_nyrz(8,day);write_com(0x80+9);break;case 6: month++;if(month==13)month=1;write_nyrz(5,month);write_com(0x80+6);break;case 7: year++;if(year==99)year=0;write_nyrz(2,year);write_com(0x80+3);break;}}}if(key5==0)//减小键{delay(5);if(key5==0){while(!key5);di();switch(s1num){case 1: miao--;if(miao==-1)miao=59;write_sfm(6,miao);write_com(0x80+0x40+7);break;case 2: fen--;if(fen==-1)fen=59;write_sfm(3,fen);write_com(0x80+0x40+4);break;case 3: shi--;if(shi==-1)shi=23;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week--;if(week==-1)week=7;display_week(week);write_com(0x80+14);break;case 5: day--;if(day==0)day=31;write_nyrz(8,day);write_com(0x80+9);break;case 6: month--;if(month==0)month=12;write_nyrz(5,month);write_com(0x80+6);break;case 7: year--;if(year==-1)year=99;write_nyrz(2,year);write_com(0x80+3);break;}}}}}void set_alarm(){if(key1==0)//功能键按下{delay(5);if(key1==0){while(!key1);flag=0;s1num2++;write_sfm(6,amiao);write_com(0x80+0x40+7);write_sfm(3,afen);write_com(0x80+0x40+4);write_sfm(0,ashi);write_com(0x80+0x40+1);di();switch(s1num2)//光标闪烁定位{case 1:write_com(0x80+0x40+7);//定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);//定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);//定位到小时的位置write_com(0x0f);break;case 4: s1num2=0;//复位,时钟走write_com(0x0c);flag=1;// write_1302(0x8e,0x00);//允许写保护write_1302 (0x8e,0x80);break;}}}if(s1num2!=0)//只有功能键按下后,增大,增小建才有效{if(key2==0)//增大建{delay(5);if(key2==0){while(!key2);di();switch(s1num2){case 1: amiao++;if(amiao==60)amiao=0;write_sfm(6,amiao);write_com(0x80+0x40+7);break;case 2: afen++;if(afen==60)afen=0;write_sfm(3,afen);write_com(0x80+0x40+4);break;case 3: ashi++;if(ashi==24)ashi=0;write_sfm(0,ashi);write_com(0x80+0x40+1);break;}}}}}void main()//主函数{Initial();lcdws=0;init();// IntConfiguration();tempchange();for(i=10;i>0;i--){dis_temp(get_temp());}while(1){keyscan();//按键扫描// while((key1&&key2&&key3&&key4&&key5)&&((fen==afen)&&(shi==ashi))) // {// beep=0;// delay(500);// beep=1;// }if(flag==1){miao=Read1302(0x81);//显示秒write_sfm(6,miao);fen=Read1302(0x83);//显示分write_sfm(3,fen);shi=Read1302(0x85);//显示小时write_sfm(0,shi);day=Read1302(0x87);//显示日write_nyrz(8,day);month=Read1302(0x89);//显示月write_nyrz(5,month);year=Read1302(0x8d);//显示年write_nyrz(2,year);week=Read1302(0x8b);//显示日期display_week(week);}else{write_1302(0x80,0x80);//时钟振荡器停止}set_alarm();}}。
基于时钟日历芯片DS1302的万年历设计

基于时钟日历芯片DS1302的万年历设计黄豪民摘要随着科学技术的发展,万年历的设计也层出不穷。
本设计以单片机AT89C51和DS1302为核心,结合译码器74HC154和驱动芯片74LS244,以及模拟键盘,LED 显示电路等构成一个可控及显示精确的万年历时间系统。
DS1302为一个实时时钟芯片,具有较高时间精度,它与单片机进行串口通信,单片机通过与它的通信,取出其时间寄存器中的值,再通过相应的电路,把时间值通过LED显示,如果显示的值与标准时间不同,此系统就经过模拟键盘灵活控制,调节DS1302中时间寄存器中的值,达到与标准时间同步。
关键词AT89C51,DS1302ABSTRACTAlong with science and technology's development, the designs of the perpetual calendar have many meanings. This design uses the microprocessor AT89C51 and the chip DS1302, with the decoder chip 74HC154, the drive chip 74LS244, the simulative keyboard, the LED display and so on to constitute the perpetual calendar system which can control and display precisely.DS1302 is a real-time clock chip and has the high time precision, it communicates with the microprocessor via the serial interface. The microprocessor takes out DS1302’s time register value by the communication, at last the LED displays the time value by the corresponding circuit. If the time value is different from the standard time, the simula tion keyboard can adjust conveniently DS1302’s time register value, achieving with the standard time synchronously.Keywords AT89C51,DS1302目录摘要 (I)ABSTRACT (II)1 绪论 (1)2 功能要求 (3)3 方案论证 (3)3.1 显示器的选择 (3)3.1.1 VFD显示器 (3)3.1.2 LED显示器 (3)3.1.3 LCD液晶显示器 (4)3.2 编程语言的选择 (4)3.2.1 单片机汇编语言 (4)3.2.2 单片机C语言 (4)3.3 微处理器的选择 (5)4 硬件电路 (6)4.1 DS1302时钟芯片 (7)4.1.1 DS1302简介 (7)4.1.2 DS1302的控制字节 (8)4.1.3 数据的输出 (9)4.1.5 DS1302的寄存器 (9)4.1.6 DS1302的读写方式 (11)4.1.7 DS1302时序图 (12)4.1.8 DS1302电路 (13)4.2 单片机AT89C51 (14)4.2.1 单片机AT89C51简介 (14)4.2.2 单片机引脚简介 (15)4.2.3 低功耗模式 (18)4.3 模拟键盘的设计 (19)4.4 LED显示器的设计 (20)4.5 74LS244芯片 (21)5 软件设计 (25)5.1 系统软件设计原理 (25)5.2 键盘扫描子程序 (25)5.3 显示子程序 (26)5.4 DS1302控制子程序 (27)5.5 主函数 (27)6 软件平台 (28)6.1 Proteus软件 (28)6.2 KEIL软件 (31)7 结论 (33)参考文献 (34)附录A:部分单片机源程序 (35)致谢 (38)1 绪论在科技日新月异发展的今天,人们对时间概念的认识显得尤为深刻,“时间就是金钱”,“时间就是生命”等警句更是激励着人们努力工作,把握时间。
基于单片机DS1302的时钟万年历(带闹钟)

#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2X; 〃1602 管脚定义sbit Icde n=P2P;sbit Icdrs=P2A2;sbit key仁卩2人3; //闹钟设置键sbit key2=P2A4;sbit key3=P1A5;〃功能键定义sbit key4=P1A6;〃增大键定义sbit key5=P1A7;〃减小键定义uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week; uchar s1num=0,s1num2=0,temp;bit flag;float f_temp;uint i,d;uchar code table2[]={0x20,0x20,0x2e,0x20,0xdf,0x43};uchar code table[]="20 - - ";uchar code table1[]=" : : ";sbit ds=P1A0;//ds18b20 信号线sbit beep=P1A4; // 蜂鸣器管脚定义sbit ACC_7 = ACCA7; //位寻址寄存器定义sbit SCLK = P1A2; // DS1302 时钟信号sbit DIO= P1A1; // DS1302 数据信号sbit CE = P1A3;//地址、数据发送子程序//void delay2(uint ms)// {// uchar t;// while(ms--); for(t=0;t<120;t++);//}// void playmusic()// {// uint i2=0,j2,k2;// while(jiepai[i2]!=0||song[i2]!=0)// {// for(j2=0;j2<jiepai[i2]*20;j2++)// {// beep=~beep;// for(k2=0;k2<song[i2]/3;k2++);// }// delay2(10);// i2++;// }// }void write_1302( uchar addr,uchar dat ) {uchar i,temp;CE=0; SCLK=0;//CE 引脚为低,数据传送中止// 清零时钟总线CE = 1; //CE 引脚为高,逻辑控制有效// 发送地址for ( i=8; i>0; i-- ) // 循环8 次移位{SCLK = 0; temp = addr;DIO = (bit)(temp&0x01);addr >>= 1;SCLK = 1;}// 发送数据for ( i=8; i>0; i-- ){SCLK = 0; temp = dat;DIO = (bit)(temp&0x01);dat >>= 1;SCLK = 1;}CE = 0;}// 数据读取子程序uchar Read1302 ( uchar addr ){unsigned char i,temp,dat1,dat2;CE=0;SCLK=0;CE = 1;// 发送地址for ( i=8; i>0; i-- ){SCLK = 0; temp = addr;DIO = (bit)(temp&0x01);addr >>= 1;// 每次传输低字节// 右移一位// 循环8 次移位// 每次传输低字节// 右移一位SCLK = 1;}// 读取数据 for ( i=8; i>0; i-- ){ACC_7=DIO; SCLK = 1; ACC>>=1; SCLK = 0;}CE=0;dat1=ACC; dat2=dat1/16;// 十六进制转十进制 dat1=dat1%16; dat1=dat1+dat2*10; return (dat1);}// 初始化 DS1302void Initial(void) // 初始化 1302 {write_1302 (0x8e,0x00);write_1302 (0x80,0x56); write_1302 (0x82,0x58); write_1302 (0x84,0x23); write_1302 (0x86,0x30); write_1302 (0x88,0x09); write_1302 (0x8c,0x10); write_1302 (0x8a,0x01); write_1302 (0x8e,0x80);void delay(uint z)// 延时 1ms{uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--);}void write_com(uchar com)//1602 写命令 {lcdrs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0;}void write_data(uchar date)//1602 写数据{ lcdrs=1; lcden=0; P0=date; delay(5); lcden=1; delay(5); lcden=0;}void dsreset(void) //DS18B20 ,初始化函数{ uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--;}// 数据进制转换2010 年 09 月 30 日 23 点 58 分 56 秒 星期一// 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 // 禁止写保护bit tempreadbit(void)// 读1 位数据函数{ uint i; bit dat; ds=0;i++; ds=1;i++;i++;//i++ 起到延时作用dat=ds; i=8;while(i>0)i--; return(dat);}uchar tempread(void) // 读一个字节数据函数{uchar i,j,dat; dat=0; for(i=1;i<=8;i++) {j=tempreadbit(); dat=(j<<7)|(dat>>1);} return(dat);void tempwritebyte(uchar dat) // 向DS18B20 写一个字节数据函数{ uint i;uchar j;bit testb; for(j=1;j<=8;j++){ testb=dat&0x01; dat=dat>>1; if(testb)// 写1 { ds=0; i++;i++; ds=1;i=8;while(i>0)i--;}else{ds=0; // 写0i=8;while(i>0)i--;ds=1; i++;i++;}}}void tempchange(void) //DS18B20 开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uint get_temp() // 获取温度{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe); a=tempread(); // 读高8 位b=tempread(); // 读低8 位temp=b;temp<<=8; // 两个字节组合成1 个字节temp=temp|a;f_temp=temp*0.0625;temp=f_temp*10+0.5;f_temp=f_temp+0.05; // 温度在寄存器中为12 位,分辨率为0.0625人return temp;}void display(uchar addr,uchar dat){ write_com(0x80+0x40+addr); write_data(0x30+dat);delay(5);}void dis_temp(uint t){uchar i;i=t/100; display(10,i); i=t%100/10;display(11,i);i=t%100%10; display(13,i);}void init()// 初始化程序{uchar num;flag=1;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80); for(num=0;num<15;num++){ write_data(table[num]); delay(5);}write_com(0x80+0x40); for(num=0;num<8;num++){ write_data(table1[num]); delay(5);} write_com(0x80+0x40+10); for(num=0;num<6;num++){write_data(table2[num]); delay(10);}}void di()// 蜂鸣器响函数{beep=0;delay(100);beep=1;}void write_sfm(uchar add,uchar date){uchar shi,ge; shi=date/10;ge=date%10; write_com(0x80+0x40+add); write_data(0x30+shi);write_data(0x30+ge);}void write_nyrz(uchar add,uchar date)// 显示年,月,日,周{ uchar shi,ge;shi=date/10;ge=date%10; write_com(0x80+add); write_data(0x30+shi);write_data(0x30+ge);}void display_week(uchar we){write_com(0x80+12);switch(we){case 1: write_data('M');delay(5); write_data('O');delay(5);write_data('N'); break;case 2: write_data('T');delay(5); write_data('U');delay(5);write_data('E'); break;case 3: write_data('W');delay(5);write_data('E');delay(5);write_data('D');break;case 4: write_data('T');delay(5);write_data('H');delay(5);write_data('U');break;case 5: write_data('F');delay(5);write_data('R');delay(5);write_data('T');break;case 6: write_data('S');delay(5);write_data('A');delay(5);write_data('T');break;case 7: write_data('S');delay(5);write_data('U');delay(5);write_data('N');break;}}void keyscan()// 按键设置{if(key3==0)// 功能键按下{flag=0;delay(5);if(key3==0){s1num++;while(!key3);di();switch(s1num)// 光标闪烁定位{case 1:write_com(0x80+0x40+7);// 定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);// 定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);// 定位到小时的位置write_com(0x0f);break;case 4:write_com(0x80+0x0e);// 定位到星期的位置if(s1num!=0)// 只有功能键按下后,增大, {if(key4==0)// 增大建{delay(5); if(key4==0){while(!key4); di();switch(s1num){case 1: miao++;if(miao==60) miao=0;write_sfm(6,miao); //write_1302(write_second ,miao);write_com(0x80+0x40+7); break;case 2: fen++;if(fen==60) fen=0;write_com(0x0f); break;case 5:write_com(0x80+0x9);// write_com(0x0f); break; case 6:write_com(0x80+0x6);// write_com(0x0f); break; case 7:write_com(0x80+0x3);// write_com(0x0f); break; case 8: s1num=0;// 复位,时钟走 write_com(0x0c); flag=1;write_1302 (0x8e,0x00); write_1302 (0x80,miao); write_1302 (0x82,fen); write_1302 (0x84,shi); write_1302 (0x86,day); write_1302 (0x88,month); write_1302 (0x8c,year); write_1302 (0x8a,week); write_1302 (0x8e,0x80); break;定位到日的位置定位到月的位置 定位到年的位置 // 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 //禁止写Y增小建才有效write_sfm(3,fen);//write_1302(write_minute,fen);write_com(0x80+0x40+4);break;case 3: shi++;if(shi==24) shi=0;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week++;if(week==8)week=1;display_week(week);write_com(0x80+14);break;case 5: day++; if(day==31) day=1;write_nyrz(8,day);write_com(0x80+9); break;case 6: month++; if(month==13)month=1; write_nyrz(5,month);write_com(0x80+6); break;case 7: year++; if(year==99) year=0;write_nyrz(2,year);write_com(0x80+3); break;}}}if(key5==0)// 减小键{delay(5);if(key5==0){while(!key5);di();switch(s1num){case 1: miao--;if(miao==-1) miao=59;write_sfm(6,miao);write_com(0x80+0x40+7);break;case 2: fen--;if(fen==-1) fen=59;write_sfm(3,fen);write_com(0x80+0x40+4);break;case 3: shi--;if(shi==-1) shi=23;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week--;if(week==-1) week=7;display_week(week);write_com(0x80+14); break;case 5: day--;if(day==0) day=31;write_nyrz(8,day);write_com(0x80+9); break;case 6: month--;if(month==0) month=12;write_nyrz(5,month);write_com(0x80+6); break;case 7: year--;if(year==-1) year=99;write_nyrz(2,year);write_com(0x80+3); break;} }}}}void set_alarm(){if(key1==0)// 功能键按下{delay(5);if(key1==0){while(!key1);flag=0;s1num2++;write_sfm(6,amiao);write_com(0x80+0x40+7);write_sfm(3,afen);write_com(0x80+0x40+4);write_sfm(0,ashi);write_com(0x80+0x40+1);di();switch(s1num2)// 光标闪烁定位{case 1:write_com(0x80+0x40+7);// 定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);// 定位到分的位置write_com(0x0f); break;case 3:write_com(0x80+0x40+1);// 定位到小时的位置write_com(0x0f); break;case 4: s1num2=0;// 复位,时钟走write_com(0x0c);flag=1;write_1302(0x8e,0x00);// 允许写保护write_1302 //(0x8e,0x80);break;if(s1num2!=0)// 只有功能键按下后,增大,增小建才有效{ if(key2==0)// 增大建{delay(5);if(key2==0){while(!key2);di();switch(s1num2){case 1: amiao++;if(amiao==60) amiao=0;write_sfm(6,amiao);write_com(0x80+0x40+7);break;case 2: afen++;if(afen==60)afen=0; write_sfm(3,afen);write_com(0x80+0x40+4);break;case 3: ashi++;if(ashi==24)ashi=0; write_sfm(0,ashi);write_com(0x80+0x40+1);break;}}}WWWWWW-nma-()八-cdwsuainip-nfconfigurafiono 八CDmpchangeo 八fo r (ll'10v 0〒)宀dislCDmp(ge匚 empo)-w h =e 3宀keyscanoy 、^M ffl Bw h i -e ((k ey l QO QO k e y 2QO QO k e y 3QO QO k e y 4QO QO key 5)QO QO ((f e n u u a f e n )QO QO (s h ll'u a s h i )))beep"八if(f-agu") 宀miaouReach302(0X81)7/和引^wriCDlsfm(6ymiao)八fenuReach302(0X83)0和引Vwmelsfm(3fen=shll'Read」3o2(ox85)0 和引亠£4wriCDlsfm(Qshi)八dayuReach302(0X87)0和引mwriCDlnyrzGday)八monfhuReach302(0X89)7/和引出 w r i CD l n yrz(5 -monfh)八year"Reach302(0x8d)y/ 和引<wriCDlnyrz(2yyear)八weekuReacH302(0x8b)y/disp-aylweek(week)八e-sewrite_1302(0x80,0x80);// 时钟振荡器停止}set_alarm();WWW}}。
(绝对正确)单片机使用DS1302设计万年历

#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define AM(X)X#define PM(X)(X+12)#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK0x8a#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8c#define DS1302_RAM( X ) (0xc0+(x)*2)#define out P0bit key_flag1=0;sbit DS1302_CLK=P2^6;sbit DS1302_IO=P2^7;sbit DS1302_RST=P2^5;sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit RS=P2^0;sbit RW=P2^1;sbit E=P2^2;uchar sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0,week_add;uint int_time=0;void delay(uint j)//1ms延时子程序{uchar i=250;for(;j>0;j--){while (i--);i=249;while (i--);i=250;}}void check_busy(void){uchar dt;do{dt=0xff;E=0;RS=0;RW=1;E=1;dt=out;}while (dt&0x80);E=0;}void write_command(uchar com){check_busy();E=0;RS=0;RW=0;out=com;E=1;_nop_();E=0;delay(1);}void write_data(uchar dat){check_busy();E=0;RS=1;RW=0;out=dat;E=1;_nop_();E=0;delay(1);}void lcd_initial(void){write_command(0x38);write_command(0x0c);write_command(0x06);write_command(0x01);delay(1);}void string(uchar ad,uchar *s){write_command(ad);while(*s>0){write_data(*s++);}}/*********DS1302********/typedef struct SYSTEM_TIME{uchar Second;uchar Minute;uchar Hour;uchar Week;uchar Day;uchar Month;uchar Year;uchar DateString[9];uchar TimeString[9];}SYSTEMTIME;SYSTEMTIME adjusted;void DS1302InputByte(uchar d)//时钟写入一字节{uchar i;ACC=d;for(i=8;i>0;i--){DS1302_IO=ACC0;DS1302_CLK=1;DS1302_CLK=0;ACC=ACC>>1;}}uchar DS1302OutputByte(void) //时钟读取一字节{uchar i;for(i=8;i>0;i--){ACC=ACC>>1;ACC7=DS1302_IO ;DS1302_CLK=1;DS1302_CLK=0;;}return(ACC) ;}void Write1302(uchar ucAddr,uchar ucDa){DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;DS1302InputByte(ucAddr);DS1302InputByte(ucDa);DS1302_CLK=1 ;DS1302_RST=0;}uchar Read1302(uchar ucAddr){uchar ucData;DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;DS1302InputByte(ucAddr|0X01);ucData=DS1302OutputByte();DS1302_CLK=1;DS1302_RST=0;return(ucData);}uchar *DateToBCD(SYSTEMTIME *Time){uchar D[8];D[0]=Time->Second/10<<4+Time->Second%10;D[1]=Time->Minute/10<<4+Time->Minute%10;D[2]=Time->Hour/10<<4+Time->Hour%10;D[5]=Time->Week/10<<4+Time->Week%10;D[4]=Time->Month/10<<4+Time->Month%10;D[3]=Time->Day/10<<4+Time->Day%10;D[6]=Time->Year/10<<4+Time->Year%10;return D;}void DS1302_SetProtect(bit flag)//是否写保护{if(flag)Write1302(0x8E,0x80);elseWrite1302(0x8E,0x00);}void DS1302_SetTime(uchar Address ,uchar value)//设置时间函数{DS1302_SetProtect(0);Write1302(Address,((value/10)<<4|(value%10)));}void DS1302_GetTime(SYSTEMTIME *Time) //获取时间{uchar ReadValue;ReadValue=Read1302(0x81);Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //将BCD码转换为十进制数ReadValue=Read1302(0x83);Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);ReadValue=Read1302(0x85);Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);ReadValue=Read1302(0x87);Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);ReadValue=Read1302(0x8b);Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);ReadValue=Read1302(0x89);Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);ReadValue=Read1302(0x8d);Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); }void DateToStr(SYSTEMTIME *Time) //将日期信息转换为字符串{Time->DateString [ 0 ]= Time->Year/10+'0';Time->DateString [ 1 ]= Time->Year%10+'0';Time->DateString [ 2 ]='-';Time->DateString [ 3 ]= Time->Month/10+'0';Time->DateString [ 4 ]= Time->Month%10+'0';Time->DateString [ 5 ]='-';Time->DateString [ 6 ]= Time->Day/10+'0';Time->DateString [ 7 ]= Time->Day%10+'0';Time->DateString [ 8 ]='\0';}void TimeToStr(SYSTEMTIME *Time) //将时间信息转换为字符串{Time->TimeString [ 0 ]= Time->Hour/10+'0';Time->TimeString [ 1 ]= Time->Hour%10+'0';Time->TimeString [ 2 ]=':';Time->TimeString [ 3 ]= Time->Minute/10+'0';Time->TimeString [ 4 ]= Time->Minute%10+'0';Time->TimeString [ 5 ]=':';Time->TimeString [ 6 ]= Time->Second/10+'0';Time->TimeString [ 7 ]= Time->Second%10+'0';Time->TimeString [ 8 ]='\0';}void Initial_DS1302(void){uchar Second;Second=Read1302(DS1302_SECOND);if(Second&0x80){DS1302_SetTime(DS1302_SECOND,0);}}void DS1302_TimeStop(bit flag){uchar Data ;Data=Read1302(DS1302_SECOND);DS1302_SetProtect(0);if(flag)Write1302(DS1302_SECOND,Data|0x80);elseWrite1302(DS1302_SECOND,Data&0x7F); }uchar *WeekToStr(SYSTEMTIME Time){uint i;uchar *z;i=Time.Week;switch(i){case 1:z="sun";break;case 2:z="mon";break;case 3:z="tue";break;case 4:z="wen";break;case 5:z="thu";break;case 6:z="fri";break;case 7:z="sat";break;}return z;}int key_scan(){int i=0;uint temp;P1=0xf0;delay(40);temp=P1;if(temp!=0xf0){i=1;}else{i=0;}return i;}uchar key_value(){uint v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'};uint temp,n=0,m=0;uchar value;P1=0xfe;temp=P1;if(temp!=0xfe)m=0;P1=0xfd;temp=P1;if(temp!=0xfd)m=1;P1=0xfb;temp=P1;if(temp!=0xfb)m=2;P1=0xf7;temp=P1;if(temp!=0xf7)m=3;P1=0xef;temp=P1;if(temp!=0xef)n=0;P1=0xdf;temp=P1;if(temp!=0xdf)n=1;P1=0xbf;temp=P1;if(temp!=0xbf)n=2;value=v[m][n];return value;}void adjust(void){if (key_scan()&&key_flag1)switch(key_value()){case'0':sec_add++;break;case'1':min_add++;break;case'2':hou_add++;break;case'3':day_add++;break;case'4':mon_add++;break;case'5':yea_add++;break;case'6':week_add++;break;default:break;}adjusted.Second+=sec_add;adjusted.Minute+=min_add;adjusted.Hour+=hou_add;adjusted.Day+=day_add;adjusted.Month+=mon_add;adjusted.Year+=yea_add;adjusted.Week+=week_add;if(adjusted.Second>59){adjusted.Second=adjusted.Second%60;adjusted.Minute++;}if(adjusted.Minute>59){adjusted.Minute=adjusted.Minute%60;adjusted.Hour++;}if(adjusted.Hour>23){adjusted.Hour=adjusted.Hour%24;adjusted.Day++;}if(adjusted.Week>7){adjusted.Week=adjusted.Week%7;}if(adjusted.Day>31)adjusted.Day=adjusted.Day%31;if(adjusted.Month>12)adjusted.Month=adjusted.Month%12;if(adjusted.Year>100)adjusted.Year=adjusted.Year%100;}void changing(void) interrupt 0 using 0{if(key_flag1)key_flag1=0;elsekey_flag1=1;}void showtime(){uint i;uchar p1[]="D:",p2[]="T:";SYSTEMTIME T;lcd_initial();Initial_DS1302();EA=1;EX0=1;IT0=1;while(1){string(0x80,p1);string(0xc0,p2);DS1302_GetTime(&T);adjusted.Second=T.Second;adjusted.Minute=T.Minute;adjusted.Hour=T.Hour;adjusted.Day=T.Day;adjusted.Month=T.Month;adjusted.Year=T.Year;adjusted.Week=T.Week;for(i=0;i<9;i++){adjusted.DateString[i]=T.DateString[i];adjusted.TimeString[i]=T.TimeString[i];}adjust();DateToStr(&adjusted);TimeToStr(&adjusted);string(0x82,adjusted.DateString);string(0x8b,&WeekToStr(adjusted));string(0xc2,adjusted.TimeString);delay(100);//break;}}void main( ){showtime();}。
基于单片机DS1302的时钟万年历

{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
sbit key3=P1A5;//功能键定义
sbit key4=P1A6;//增大键定义
sbit key5=P1A7;//减小键定义
uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week;
uchar s1num=0,s1num2=0,temp;
bit flag;
{
write_1302 (0x8e,0x00);//write_1302 (0x80,0x56);
write_1302 (0x82,0x58);//write_1302 (0x84,0x23);//
write_1302 (0x86,0x30);//
write_1302 (0x88,0x09);//
write_1302 (0x8c,0x10);//write_1302 (0x8a,0x01);//write_1302 (0x8e,0x80);
{
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
写命令
delay(5);
lcden=0;
void write_data(uchar date)//1602写数据
{
lcdrs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;}
SCLK= 0;}CE=0;
dat1=ACC;
dat2=dat1/16;//
基于单片机和DS1302电子万年历的方案设计书

(1) 时钟芯片DS1302的工作原理:DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图所示。
为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表6为DS1302的日历、时间寄存器内容:“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。
“WP”是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
(2) DS1302的控制字节DS1302的控制字如表-1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出表-1 DS1302的控制字格式RAM RD1 A4 A3 A2 A1 A0/ CK /WR(3) 数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如下图1所示图1 DS1302读/写时序图(4) DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表-2。
表-2 DS1302的日历、时间寄存器此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
基于单片机的电子万年历的设计与实现毕业论文

保密类别编号毕业论文基于单片机的电子万年历的设计与实现摘要电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行.它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能.在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
在硬件与软件设计时,没有良好的基础知识和实践经验会受到很大限制,每项功能实现时需要那种硬件,程序该如何编写,算法如何实现等,没有一定的基础就不可能很好的实现.在编写程序过程中发现以现有的相关知识要独自完成编写任务困难重重,在老师和同学的帮助下才完成了程序部分的编写.关键词:单片机万年历DS1302 STC89C52第1章绪论 (1)1。
1 课题研究的背景 (1)1。
2 国内外关于该论题的研究现状和发展趋势 (1)1。
3 本课题研究的目的 (1)第2章系统基本方案选择和论证 (1)2。
1 单片机芯片的选择 (1)2.2 显示模块选择方案和论证 (1)2.3 时钟芯片的选择方案和论证 (1)2。
4 温度传感器的选择方案与论证 (2)第3章系统的硬件设计与实现 (3)3.1电路设计框图 (3)3.2 主要单元电路的设计 (4)3.3 单片机中断系统 (5)3.4 温度采集模块设计 (8)3。
5显示模块的设计 (9)3.6系统的软件设计 (10)结论1。
硬件测试 (12)2.软件测试 (12)参考文献 (13)附录 (14)后记 (16)第1章绪论1.1 课题研究的背景随着微电子技术和超大规模集成电路技术的不断发展家用电子产品不但种类日益丰富而且变得更加经济实用。
基于DS1302的电子万年历设计说明

基于DS1302的电子万年历设计摘要:本文介绍了一种智能一体化的电子万年历系统,该设计采用DS1302时钟芯片,主控芯片STC89C52型单片机,显示器件NOKIA 5110 LCD,外部手动设置模块键盘组成了电子万年历小系统,NOKIA 5110 LCD能一目了然地显示出年月日星期小时分秒,满足了人们在读取时更加直接的需要。
电子万年历集时间,日期,温度,闹钟于一体,且电路简洁,成本低廉,显示准确,符合了人们对时间的各种需求,使人们生活更加方便快捷。
关键词:万年历 STC89C52 DS1302 NOKIA 5110The Design of Electronic Calendar Based on DS1302 Name:Zhang qianqian Student Id:2 Advisor:Wang zhongxinAbstract: This paper introduces a kind of intelligent electronic calendar system, this calendar small system is made up of the DS1302 clock chip, main control chip microcontroller STC89C52 , NOKIA 5110 LCD display device, external manual setup module keyboard. NOKIA 5110 LCD can clearly show whole time to meet people every need for time request. Electronic calendar include time, date, temperature, the alarm clock module in one system, the system circuit is simple, the cost is low but it can display accurate time, it can meet the different needs of people to time and help people’ life become more convenient and efficient..Keywords: calendar STC89C52 DS1302 NOKIA 5110目录1.论序 (1)1.1课题背景 (1)1.2基于DS1302的电子万年历设计的目的和意义 (1)1.2.1设计目的 (1)1.2.2设计意义 (1)1.3现代电子万年历系统设计的发展状况 (1)1.4课题容 (1)1.5本章小结 (1)2.基于DS1302的电子万年历系统总体设计方案 (2)2.1总体设计框图 (2)2.2系统设计的功能要求 (2)2.3系统设计的方案论证 (2)2.3.1单片机控制模块的选择 (2)2.3.2时钟芯片的选择 (3)2.3.3键盘电路的选择 (3)2.3.4 显示电路的选择 (3)2.4本章小结 (3)3.基于DS1302的电子万年历设计系统硬件电路设计 (4)3.1系统硬件电路设计 (4)3.2系统核心电路——单片机STC89C52 (4)3.2.1 STC89C52主要功能 (4)3.2.2 STC89C52主要引脚及其功能 (5)3.3时钟电路设计 (6)3.3.1 DS1302的性能特征 (6)3.3.2 DS1302的工作原理及数据操作 (7)3.4键盘和显示电路的设计 (9)3.4.1键盘接口设计 (9)3.4.2显示电路设计 (9)3.5本章小结 (11)4. 基于DS1302的电子万年历软件设计 (11)4.1基于DS1302的电子万年历设计系统程序设计要求 (11)4.2基于DS1302的电子万年历设计系统主程序设计 (11)4.2.1液晶模块初始化程序 (11)4.2.2DS1302时钟控制模块初始化程序 (11)4.2.3定时器T0初始化程序 (11)4.2.4时钟程序和中断程序 (11)4.3N OKIA5110液晶显示模块的程序设计 (11)4.4DS1302时间控制模块的程序设计 (11)4.5闹钟程序设计 (13)4.6本章小结 (14)5.总结 (14)1.1课题背景随着科技的发展社会的进步,人类从观太阳、摆钟到现在电子钟得知时间,不断的研发新的计时产品。
基于51单片机DS1302万年历课程设计报告

课程名称:微机原理课程设计题目:基于DS1302芯片万年历摘要DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM,通过简单的串行接口与单片机进行通信实时时钟/日历电路.提供秒、分、时、日、日期.、月、年的信息,每月的天数和闰年的天数可自动调整时钟。
本次课程设计的是使用专门的时钟芯片DS1302在数码管上显示的数字电子钟,并能通过按键对其进行调时和校准以及实现年月日。
DS1302是一种高性能、低功耗、带RAM的实时时钟芯片,它能够对时,分,秒进行精确计时,它与单片机的接口使用同步串行通信,仅用3条线与之相连接,就可以实现STC-51单片机对其进行读写操作,把读出的时间数据送到数码管上显示。
程序运行时,数码管将从当前时间开始显示,通过调节K2键和K3键可以分别对小时和分钟进行调整,调整后,时钟以新的时间为起点继续刷新显示,通过调节K1键可以切换年月日和时钟显示。
关键字:STC-51单片机,DS1302,数码管,动态扫描,调时,切换,秒闪;目录一、设计任务与要求 (4)1.1设计任务 (4)1.2设计要求 (4)1.3发挥部分 (4)1.4创新部分 (4)二、方案总体设计 (5)2.1设计目的 (5)2.2硬件功能描述 (5)2.3设计方案选择 (5)2.4总体设计 (6)2.5总体方案及基本工作原理 (6)三、硬件设计 (7)3.1 STC89C51芯片 (7)3.2电源模块及晶振模块 (7)3.3 DS1302 (8)3.4数码管显示模块 (9)3.5蜂鸣器部分 (10)3.6按键部分 (11)四、软件设计 (13)4.1软件流程图 (13)4.2 软件设计 (13)主函数部分: (13)五、系统仿真和调试 (15)5.1 仿真软件简介 (15)5.2硬件调试 (15)5.3软件调试 (15)5.4使用说明 (16)六、设计总结与体会 (18)6.1学习方面 (18)6.2工作方面 (18)七、参考文献 (19)一、设计任务与要求1.1设计任务DS1302万年历;1.2设计要求利用DS1302生成万年历,时钟可调,通过四位数码管显示,并可实现秒闪功能,同时蜂鸣器闹铃;1.3发挥部分设置按键K3用来切换显示时钟和年月日;1.4创新部分只设置了两个按键K1和K2来调节时分,时钟到24归零,分钟到60归零,分钟有长按迅速调节功能。
基于51单片机和DS1302的万年历的方案设计书

题目:基于51单片机和DS1302万年历的设计作者:所在学院:信息科学与工程学院专业年级:学号:指导教师:职称:讲师2013年 6月 13日Proteus简介:Proteus软件是英国Labcenter electronics公司出版的EDA工具软件(该软件中国总代理为广州风标电子技术有限公司)。
它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。
它是目前最好的仿真单片机及外围器件的工具。
虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教案的教师、致力于单片机开发应用的科技工作者的青睐。
Keil简介:2009年月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。
新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
基本组成:硬件控制电路主要用了AT89C51芯片处理器、1602LCD显示器、DS1302实时时钟。
根据各自芯片的功能互相连接成电子万年历的控制电路。
软件控制程序主要有主控程序、电子万年历的时间控制程序、时间显示及温度显示程序等组成。
AT89C51单片机:本系统采用的是美国ATMEL公司生产的AT89C51单片机,首先我们来熟悉一下AT89C51单片机的外部引脚和内部结构。
1.单片机的引脚功能AT89C51单片机有40个引脚。
●Vcc:电源电压+5V●GND:接地●P0口:P0口是一组8位漏极开路型双向I/O口,也即地址/数据总线复用口。
作为输出口用时,每位能驱动8个TTL逻辑门电路,对端口写“1”可作为高阻抗输入端用。
基于51单片机电子万年历设计

一、引言电子万年历是一种以数字形式实时显示日期、星期和时间等信息的电子设备。
在现代人日常生活中,万年历是一种常见的小型电子产品。
本文将基于51单片机设计一款简单实用的电子万年历。
二、设计原理1.时钟模块:采用DS1302实时时钟模块。
DS1302通过三线式串行接口与51单片机进行通信,可以实时获取日期、星期和时间等信息。
2.显示模块:使用数码管显示日期、星期和时间等信息。
共使用四块共阳数码管,采用数码管模块进行驱动,通过IO口进行数据传输。
3.按键模块:设计四个按键,分别为设置、上、下和确定。
通过按键来调整日期、星期和时间等信息。
4.闹钟功能:加入闹钟功能,可以设定闹钟时间,到达设定时间时,会有提示音。
5.温湿度传感器:加入温湿度传感器,可以实时监测环境温湿度,并在数码管上进行显示。
6.外部电源:由于51单片机工作电压较高,需要使用外部电源进行供电。
三、硬件设计1.电源电路:使用稳压电源芯片LM7805进行5V稳压,将稳压后的电压供给单片机和各个模块。
2.时钟模块:DS1302模块与单片机通过串行通信进行连接。
时钟模块上的时钟信号、数据信号和复位信号分别与单片机的IO口相连。
3.数码管显示模块:共有四块共阳数码管,通过595芯片进行驱动。
单片机的IO口与595芯片的串行、时钟和锁存引脚相连,595芯片的输出引脚与数码管的各段相连。
4.按键模块:通过电阻分压来实现按键功能,按下按键时,相应的IO口会被拉低。
5.闹钟功能:使用蜂鸣器来产生提示音,通过IO口与单片机相连。
6.温湿度传感器:使用DHT11温湿度传感器。
传感器的数据引脚通过IO口与单片机相连。
四、软件设计1.时钟显示:通过DS1302获取日期、星期和时间等信息,将其转化为数码管需要的编码格式,并通过595芯片进行显示。
2.按键操作:对按键进行扫描,根据按键的不同操作进行相应的处理。
例如按下设置键进行日期和时间的设置,按下上下键进行数值的变化,按下确定键进行数值的确认。
基于51单片机和DS1302的电子万年历任务书

2)完成相关的技术文档和毕业设计论文
2、毕业设计的主要技术指标
1)显示阳历年、月、日、时、分、秒、星期及阴历年、月、日,能标明是否闰月
2)用液晶进行显示,用按键进行调整
3) 实现闹铃功能
3、毕业设计的基本要求:
1)完成电子系统的方案设计,技术调试,硬件实现
2)完成技术指标中的各项要求为优秀
毕业设计任务书
xxx年xx月xx日
题目
(包括副标题)
基于51单片机和DS1302的电子万年历
教师姓名
xxx
系别
xxx
职称xLeabharlann x学生姓名xxx班级
xxx
学号
xxx
课题成果形式
论文□设计说明书□实物■软件□其它□
1.毕业设计(论文)课题任务的内容和要求(如原始数据、技术要求、工作要求等):
1、毕业设计的主要内容:
2.毕业设计(论文)工作进度计划:
周 次
工作内容
第一周、第二周
第三周,第四周
第五周,第六周
第七、八、九周
第十、十一、十二周
查找资料、设计电路
方案论证、购买元件
制作电路、程序设计
系统制作、整体调试
总结论文、准备答辩
教研室(学科组)主任签字:
基于DS1302与数码管设计的电子万年历

交通职业技术学院毕业论文毕业论文题目:基于DS1302与数码管设计的电子万年历学生:金如学号:1213223217院(系):机电工程学院专业:机电一体化(自动化技术)班级:一体化123班指导教师:建起止时间: 2014 年11 月—— 2014 年 12 月基于DS1302与数码管设计的电子万年历摘要:单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以与我们生活中广泛使用的各种智能IC卡、电子产品等,这些都离不开单片机。
单片机是将CPU、RAM、ROM、定时器、计数器和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上,而51系列单片机是各单片机中最为典型和最有代表性的一种。
本文通过对一个基于DS1302与数码管的电子万年历的设计,从而达到学习、了解单片机相关指令在各方面的应用。
系统由主控制器AT89C51、实时钟电路DS1302、显示电路组成,能实现时钟日历显示的功能,能进行时、分、秒的显示。
关键词:单片机;DS1302;数码管;电子万年历目录1 引言42 设计方案与要求42.1 功能要求42.2 系统基本方案选择和论证42.2.1单片机芯片的选择和论证 (4)2.2.2显示模块的选择和论证 (5)2.2.3时钟芯片的选择和论证 (5)2.3 电路设计最终方案决定52.4 各硬件基本原理与介绍52.4.1AT89C51单片机原理与介绍 (5)2.4.2LED数码管显示原理与介绍 (6)2.4.3DS1302原理与介绍 (6)2.4.474HC573原理与介绍 (6)3 硬件设计部分73.1 电路设计框图73.2 系统硬件概述73.3 主要单元电路的设计73.3.1单片机主控制模块的设计 (7)3.3.2时钟电路DS1302的设计 (8)3.3.3显示模块的设计 (10)3.3.4锁存器模块的设计 (11)4 软件设计部分114.1 软件设计概述114.2 Keil C51和Proteus介绍124.2.1Keil C51的介绍 (12)4.2.2Proteus的介绍 (12)4.3 整体设计125 结束语141 引言随着微电子技术的高速发展,随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 DS1302实时时钟(1) 时钟芯片DS1302的工作原理:DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST 端置“1”,最后才给予SCLK脉冲;读/写时序如下图所示。
为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表6为DS1302的日历、时间寄存器内容:“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。
“WP”是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
(2) DS1302的控制字节DS1302的控制字如表-1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出表-1 DS1302的控制字格式RAM RD1 A4 A3 A2 A1 A0/ CK /WR(3) 数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如下图1所示图1 DS1302读/写时序图(4) DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD 码形式,其日历、时间寄存器及其控制字见表-2。
表-2 DS1302的日历、时间寄存器此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM 相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM 相关的寄存器分为两类:一类是单个RAM 单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H ~FDH ,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM 寄存器,此方式下可一次性读写所有的RAM 的31个字节,命令控制字为FEH(写)、FFH(读)。
写寄存器 读寄存器 Bit7 Bit6Bit5Bit4Bit3Bit2Bit1Bit080H 81H CH 10秒秒 82H 83H 10分 分 84H 85H 12/24 0 10时时 AM /PM 86H 87H 0 0 10日 日 88H 89H 0 0 0 10月 月8AH 8BH 0 0 0 0 0 星期 8CH 8DH 10 年 年 8EH8FHWP0 0 00 02 方案论证与设计2.1控制器部分方案设计硬件控制电路主要用了AT89C52芯片处理器、1602LCD 显示器、DS1302实时时钟、DB18B20温度传感器。
根据各自芯片的功能互相连接成电子万年历的控制电路。
软件控制程序主要有主控程序、电子万年历的时间控制程序、时间显示及温度显示程序等组成。
设计框图如图2.1所示图2.1 框图设计2.2 显示部分的方案论证方案一:采用8段数码管虽经济实惠,但操作比液晶显示来说略显繁琐。
方案二:液晶显示方式。
液晶显示效果出众,可以运用菜单项来方便操作,比较简单,所以,最后选择液晶显示方案。
显示电路图如图2.2所示。
图2.2 液晶显示电路2.3 实时时钟电路设计图2.3是 DS1302与单片机的连接,其中Vcc1为后备电源,Vcc2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V 时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768KHz 晶振。
AT89C52主控模块1602液晶显示DS1302时钟电路 独立键盘电路DS18B20实时环境温度采集电路蜂鸣器图2.3 DS1302时钟电路2.4 温度采集模块设计如图2.4所示,采用数字式温度传感器DS18B20,它是数字式温度传感器,具有测量精度高,电路连接简单特点,此类传感器仅需要一条数据线进行数据传输,使用P3.7与DS18B20的I/O口连接加一个上拉电阻,Vcc接电源,Vss接地。
图2.4 DS18B20温度采集模块2.5 功能按钮设计当按钮被按下时,该按钮对应的I/O口被拉为低电平,松开时按钮对应的I/O口由内部的上拉电阻将该I/O拉为高电平,如图2.5所示:图2.5 键盘电路设计2.6 总体电路图3 软件设计流程3.1 系统总流程图系统总体流程图如图3.1所示,系统流程图设计分析如下:首系统初始化,系统运行,当有设置键按下时进入时间修改模式,无按键按下时读取时间温度等数据送入显示器显示。
在时间修改模式下设置时间完成后再将时间送入显示器显示。
图3.1 系统流程图3.2 温度程序流程图温度读取程序流程图如图3.2所示。
流程图分析:开始进入初始化DS18B20,就是通过主机拉低单线产生复位脉冲然后释放总线,如果有应答就发起ROM命令,当成功执行操作命令后,就使用温度转换,当温度转换完成后又初始化DS18B20是否有应答脉冲,若有就发起读暂存器和CRC命令,同时读出第一第二字节即温度数据。
图3.2 温度读取程序流程图3.3 DS1302时钟程序流程图时钟流程图如图3.3所示,流程图分析:DS1302开始计时时,首先进行初始化,当有中断信号时,读取时钟芯片的时间数据送入液晶显示。
这时若有设置键按下,进行时间修改,完成后将时间数据送入1302芯片,若没有按键按下,直接送入EPROM中,送入液晶显示。
图3.3 时钟程序流程图DS1302时钟部分子程序void write_byte(uchar dat)//写一个字节{ACC=dat;RST=1;for(a=8;a>0;a--){IO=ACC0;SCLK=0; //产生上升沿写入数据,从低位写入SCLK=1;ACC=ACC>>1;}}uchar read_byte()//读一个字节{RST=1;for(a=8;a>0;a--){ACC7=IO;SCLK=1; //产生下降沿输出数据,先输出低位,保存到ACC中SCLK=0;ACC=ACC>>1;}return (ACC);}void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据{RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;}uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址{uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);}uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制{uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}void ds1302_init() //1302芯片初始化子函数(2012-06-18,12:00:00,week7){RST=0;SCLK=0;write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00 write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00 write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12 write_1302(0x8a,0x07);//向DS1302内写周寄存器8aH写入初始周数据4write_1302(0x86,0x17);//向DS1302内写日期寄存器86H写入初始日期数据18 write_1302(0x88,0x06);//向DS1302内写月份寄存器88H写入初始月份数据06 write_1302(0x8c,0x12);//向DS1302内写年份寄存器8cH写入初始年份数据12 write_1302(0x8e,0x80); //打开写保护}3.4 LCD显示程序流程图显示流程图如图3.4所示,流程图分析如下:首先对1602显示屏进行初始化(初始化大约持续10ms),然后检查忙信号,若BF=0,则获得显示RAM地址,写入相应的数据显示。
若BF=1,则代表模块正在进行内部操作,不接受任何外部指令和数据,直到BF=0为止。
图3.4 LCD显示程序流程图4万年历的仿真与调试结果上电后的显示秒调节功能按键,自上而下功能依次为调节按键、加按键、减按键5心得体会本次设计是我们遇到过的较大的设计,所以遇到的问题也比较的多,尤其是以前没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了不少的困难,在同学的帮助才逐一克服了难题,学习到了不少的专业知识。
在整个设计过程之前,我已经在网上找了相关方面的资料,万事开始难,一开始不知道从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块可以在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的日子里,我会进一步加强自己的动手能力,丰富自己的知识面。
参考文献[1]李朝青.单片机原理及接口技术[M],北京:北京航天航空大学出版社,2005[2]李广弟.单片机基础[M],北京:北京航空航天大学出版社,2000[3]万光毅.单片机实验与实践教程[M],北京:北京航空航天大学出版社,2003[4]唐亚平、李移伦.单片机原理实训与学习指导[M],长沙:中南大学出版社,2006[5]刘军.单片机原理与接口技术[M],华东理工大学出版社,2006[6]谢自美.电子线路设计、实验、测试[M],武汉:华中理工大学出版社,2000附件万年历源程序#include<reg51.h>#include"DS18B20_3.H"#define uint unsigned int#define uchar unsigned charuchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;//flag用于读取头文件中的温度值,和显示温度值#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)sbit rs=P2^6; //寄存器选择sbit en=P2^7; //下降沿使能sbit rw=P2^5; //读写信号线//DS1302时钟芯片与C51之间的引脚连接定义sbit IO=P3^4;//数据线sbit SCLK=P3^6;sbit RST=P3^5;sbit ACC0=ACC^0;sbit ACC7=ACC^7;ACC累加器=AACC.0=E0H//校时按键与C51的引脚连接定义sbit key1=P2^0; //设置键sbit key2=P2^1; //加键sbit key3=P2^2; //减键sbit buzzer=P1^5;//蜂鸣器,端口低电平响uchar code tab1[]={"20 - - "}; //年显示的固定字符uchar code tab2[]={" : : "};//时间显示的固定字符//延时函数,后面经常调用void delay(uint xms)//延时函数,有参函数{uint x,y;for(x=xms;x>0;x--)for(y=120;y>0;y--);}void write_1602com(uchar com)//****液晶写入指令函数****{rs=0;//数据/指令选择置为指令rw=0; //读写选择置为写P0=com;//送入数据delay(1);en=1;//拉高使能端,为制造有效的下降沿做准备delay(1);en=0;//en由高变低,产生下降沿,液晶执行命令}void write_1602dat(uchar dat)//***液晶写入数据函数****{rs=1;//数据/指令选择置为数据rw=0; //读写选择置为写P0=dat;//送入数据delay(1);en=1; //en置高电平,为制造下降沿做准备delay(1);en=0; //en由高变低,产生下降沿,液晶执行命令}void lcd_init()//***液晶初始化函数****{write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据write_1602com(0x0c);//开显示不显示光标write_1602com(0x06);//整屏不移动,光标自动右移write_1602com(0x01);//清显示write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示for(a=0;a<14;a++){write_1602dat(tab1[a]);//向液晶屏写日历显示的固定符号部分//delay(3);}write_1602com(er+2);//时间显示固定符号写入位置,从第2个位置后开始显示for(a=0;a<8;a++){write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号//delay(3);}}void write_byte(uchar dat)//写一个字节{ACC=dat;RST=1;for(a=8;a>0;a--){IO=ACC0;SCLK=0; //产生上升沿写入数据,从低位写入SCLK=1;ACC=ACC>>1;}}uchar read_byte()//读一个字节{RST=1;for(a=8;a>0;a--){ACC7=IO;SCLK=1; //产生下降沿输出数据,先输出低位,保存到ACC中SCLK=0;ACC=ACC>>1;}return (ACC);}void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据{RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;}uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址{uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);}uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制{uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}void ds1302_init() //1302芯片初始化子函数(2012-06-18,12:00:00,week7){RST=0;SCLK=0;write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12write_1302(0x8a,0x07);//向DS1302内写周寄存器8aH写入初始周数据4write_1302(0x86,0x17);//向DS1302内写日期寄存器86H写入初始日期数据18write_1302(0x88,0x06);//向DS1302内写月份寄存器88H写入初始月份数据06write_1302(0x8c,0x12);//向DS1302内写年份寄存器8cH写入初始年份数据12write_1302(0x8e,0x80); //打开写保护}//温度显示子函数void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显示位置{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码write_1602dat(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码write_1602dat(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码}//时分秒显示子函数void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//年月日显示子函数void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(yh+add);//设定显示位置为第一个位置+addwrite_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}void write_week(uchar week)//写星期函数{write_1602com(yh+0x0c);//星期字符的显示位置switch(week){case 1:write_1602dat('M');//星期数为1时,显示write_1602dat('O');write_1602dat('N');break;case 2:write_1602dat('T');//星期数据为2时显示write_1602dat('U');write_1602dat('E');break;case 3:write_1602dat('W');//星期数据为3时显示write_1602dat('E');write_1602dat('D');break;case 4:write_1602dat('T');//星期数据为4是显示write_1602dat('H');write_1602dat('U');break;case 5:write_1602dat('F');//星期数据为5时显示write_1602dat('R');write_1602dat('I');break;case 6:write_1602dat('S');//星期数据为6时显示write_1602dat('T');write_1602dat('A');break;case 7:write_1602dat('S');//星期数据为7时显示write_1602dat('U');write_1602dat('N');break;}}//****************键盘扫描有关函数**********************void keyscan(){if(key1==0)//---------------key1为功能键(设置键)--------------------{delay(9);//延时,用于消抖动if(key1==0)//延时后再次确认按键按下{buzzer=0;//蜂鸣器短响一次delay(20);buzzer=1;while(!key1);key1n++;if(key1n==9)key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环switch(key1n){case 1: TR0=0;//关闭定时器//TR1=0;write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标write_1602com(0x0f);//设置光标为闪烁temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302write_1302(0x8e,0x00);write_1302(0x80,0x80|temp);//miaowrite_1302(0x8e,0x80);break;case 2: write_1602com(er+6);//按2次fen位置显示光标//write_1602com(0x0f);break;case 3: write_1602com(er+3);//按动3次,shi//write_1602com(0x0f);break;case 4: write_1602com(yh+0x0e);//按动4次,week//write_1602com(0x0f);break;case 5: write_1602com(yh+0x0a);//按动5次,ri//write_1602com(0x0f);break;case 6: write_1602com(yh+0x07);//按动6次,yue//write_1602com(0x0f);break;case 7: write_1602com(yh+0x04);//按动7次,nian//write_1602com(0x0f);break;case 8:write_1602com(0x0c);//按动到第8次,设置光标不闪烁TR0=1;//打开定时器temp=(miao)/10*16+(miao)%10;write_1302(0x8e,0x00);write_1302(0x80,0x00|temp);//miao数据写入DS1302write_1302(0x8e,0x80);break;}}}//------------------------------加键key2----------------------------if(key1n!=0)//当key1按下以下。