基于单片机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归零,分钟有长按迅速调节功能。
51单片机万年历实验DS1302可按键设置时钟

*选择设置加 1。
* 注意
:
*******************************************************************************
/
#include<reg51.h> #include"lcd.h" #include"ds1302.h"
sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3;
LcdInit();
Ds1302Init();
while(1)
{
if(SetState==0)
{
Ds1302ReadTime();
}
else
{ if(K1==0)
//检测按键 K1 是否按下
{ Delay10ms(); //消除抖动
if(K1==0)
{
SetPlace++;
if(SetPlace>=7)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////以下是 主文件 main.c 的内容
void Int0Configuration();
void LcdDisplay();
unsigned char SetState,SetPlace; void Delay10ms(void); //误差 0us
/******************************************************************************
ds1302_万年历

/***************************************************************系统名称:电子万年历日期:2008,7,18功能描述:LCD12864串行模式显示,DS1302读取时间年月份,18B20 读取温度****************************************************************/#include <reg51.h>#include <intrins.h>#include <stdio.h>#define uchar unsigned char#define uint unsigned int/*------------LCD12864相关声明-----------------------------*/#define com 0#define dat 1sbit cs =P1^6;sbit sid=P1^4;sbit sck=P1^2;uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.uchar code TAB2[]={"20 年月日"}; //第二行uchar code TAB3[]={"星期: : "}; //第三行uchar code TAB4[]={"室温: ℃"}; //第四行/*----------------------DS1302相关声明-------------------------*/char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.0x18,0x06,0x06,0x08}; //日:月:星期:年.uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/sbit T_IO=P2^5; /* 实时时钟的数据线*/sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;/*--------------18B20相关声明-------------------------------*/uchar dis1[16];sbit DQ=P1^0; /*DS18B20温度检测*//*----------键盘相关声明-------------------------------------*/sbit key=P3^2; //功能键sbit key1=P3^3; //只有加1键uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志./*--------------以下为LCD12864相关函数--------------------------*//**************************************************************函数名称:void delay1ms(uint x)函数功能: 延时1MS***************************************************************/void delay1ms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<120;j++);}/************************************************************** 函数名称:void w_12864byte(uchar byte)函数功能: 写字节**************************************************************/ void w_12864byte(uchar byte){uchar i;for(i=0;i<8;i++){sck=0;byte<<=1;sid=CY;sck=1;}}/************************************************************** 函数名称:uchar r_12864byte(void)函数功能: 读字节***************************************************************/ uchar r_12864byte(void){uchar i,temp1,temp2;temp1 = 0;temp2 = 0;for(i=0;i<8;i++){temp1=temp1<<1;sck = 0;sck = 1;sck = 0;if(sid) temp1++;}for(i=0;i<8;i++){temp2=temp2<<1;sck = 0;sck = 1;sck = 0;if(sid) temp2++;}return ((0xf0&temp1)+(0x0f&temp2));}/************************************************************** 函数名称:void c_12864busy( void )函数功能: 检测忙函数**************************************************************/ void c_12864busy( void ){dow_12864byte(0xfc); //11111,RW(1),RS(0),0while(0x80&r_12864byte());}/************************************************************** 函数名称:void w_12864(bit dat_com,uchar byt)函数功能: 写入函数***************************************************************/ void w_12864(bit dat_com,uchar byt){uchar temp;if(dat_com==0) //为零,写入指令temp=0xf8; //11111,RS(0),RW(0),0else //否则,写入数据temp=0xfa; //11111,RS(1),RW(0),0cs=1;c_12864busy();w_12864byte(temp);w_12864byte(byt&0xf0); //写入高四位w_12864byte(byt<<4); //写入低四位cs=0;}/************************************************************** 函数名称:void init_12864(void)函数功能:初始化12864***************************************************************/ void init_12864(void){w_12864(com,0x30); //基本指令功能.w_12864(com,0x0c); //显示打开,关光标,反白关.w_12864(com,0x01); //清屏指令.w_12864(com,0x06); //AC自动加一}/*----------------以下为DS1302相关函数-------------------------*//************************************************************** 函数名称:void w_1302byte(uchar date)函数功能:写一个字节(上升沿)***************************************************************/ void w_1302byte(uchar date){ uchar i;datbyte=date;for(i=0;i<8;i++){ T_IO=datbyte0; //写最低位T_CLK=0;T_CLK=1;datbyte>>=1;}}/************************************************************** 函数名称:uchar r_1302byte(void)函数功能:读一个字节(下降沿)***************************************************************/ uchar r_1302byte(void){ uchar i;datbyte=0;for(i=0;i<8;i++){ datbyte7=T_IO; //读最低位T_CLK=1;T_CLK=0;datbyte>>=1;}return(datbyte);}/*************************************************************** 函数名称:void write_1302(uchar addr,uchar date)函数功能: 指定位置写数据****************************************************************/ void write_1302(uchar addr,uchar date){ T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);w_1302byte(date);T_CLK=0;T_RST=0;}/************************************************************** 函数名称:uchar read_1302(uchar addr)函数功能: 指定位置读数据****************************************************************/ uchar read_1302(uchar addr){ uchar dat1,dat2,temp;T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);temp=r_1302byte();T_RST=0;T_CLK=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/***************************************************************函数名称:void init_1302(void)函数功能: 初始化*****************************************************************/ void init_1302(void){ uchar i;uchar addr=0x80;write_1302(0x8e,0x00);for(i=0;i<7;i++){write_1302(addr,TAB_1302[i]);addr+=2;}write_1302(0x8e,0x80);}/**************************************************************** 函数名称:void get_1302(void)功能说明:读取DS1302时钟信息.*****************************************************************/ void get_1302(void){ uchar i,addr=0x81;for(i=0;i<7;i++){ TAB_1302[i]=read_1302(addr);addr+=2;}}/*---------------以下为18B20相关函数-----------------------------*//******************************************************************函数名称:void delay (uint x)功能说明:若机器周期为1us,则本延时程序为延时4*x(us)******************************************************************/ void delay (uint x) //本板延时8us{while (--x);}/***************************************************************** 函数名称:uchar bus_rest(void)功能说明:产生单总线系统信号的总线复位信号,并返回总线上是否存在单总线器件信息******************************************************************/ uchar bus_rest(void){uchar presence;DQ=0; //将DQ信号线拉低delay(29); //持续48USDQ=1; //释放总线delay(3); //等待从设备将总线拉低presence=DQ; //保存当前总线状态delay(25); //等待总线初始化过程结束return presence;//返回是否有从设备将总线拉低}/**************************************************************** 函数名称:uchar r_1820BYTE(void)功能说明:向单总线读取一个数据字节*****************************************************************/ uchar r_1820BYTE(void){uchar i=0;uchar date = 0;for (i=8;i>0;i--){DQ = 0; // 将DQ信号线拉低启动读时隙DQ=1;// 释放总线,等待从机动车辆返回数据位delay(1); //越接近15us越好; 准备采样总线上的信号date>>=1 ;if (DQ)date=date|0x80;delay(6);}return(date);}/***************************************************************** 函数名称:void w_1280Byte(uchar bytevalue)功能说明:向单总线写一个数据字节******************************************************************/ void w_1280Byte(uchar bytevalue){uchar i;for(i=0;i<8;i++){DQ=0; // 将DQ信号线拉低启动读时隙DQ=bytevalue&0x01; //delay(5);//等待写时隙结束DQ=1; //释放bytevalue>>=1;}delay(5); ////等待写时隙结束}/***************************************************************** 函数名称:uint read_T(void)功能说明:读取1820温度*******************************************************************/ uint read_T(void){uchar a=0;uchar b=0;uint t=0;bus_rest();w_1280Byte(0xCC); // 跳过读序号列号的操作;w_1280Byte(0x44); // 启动温度转换,模数转化;bus_rest();w_1280Byte(0xCC); //跳过读序号列号的操作;a=r_1820BYTE();// 低8位b=r_1820BYTE();// 高8位t=(b*256)+a;return(t);}/**************************************************************函数名称:void show_T(uint temp)函数功能:显示温度**************************************************************/void show_T(uint temp){int i;float ftemp;ftemp = temp* 0.0625;w_12864(com,0x98+3);for(i=0;i<5;i++)w_12864(dat,dis1[i]); //写入温度}/*---------------以下为显示相关函数--------------------------*//******************************函数名称: void fenli(uchar x,uchar y,uchar val)功能描述: 指定位置写入数据********************************/void fenli(uchar x,uchar y,uchar val){ uchar ge,shi,addr,i=0;if(val==5)//星期数字显示的转换为中文{w_12864(com,0x88+2);for(i=0;i<2;i++){if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]);if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]);if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);}}else{shi=TAB_1302[val]/10;//分离十位ge=TAB_1302[val]%10;if(x==1)x=0x80;if(x==2)x=0x90;if(x==3)x=0x88;if(x==4)x=0x98;addr=x+y;w_12864(com,addr);//指定位置w_12864(dat,0x30+shi);//写入w_12864(dat,0x30+ge);}}/*************************************************************函数名称:void display(void)功能描述: 显示函数**************************************************************/ void display(void){ get_1302(); //读1302fenli(3,7,0); //读秒fenli(3,5,1); //读分fenli(3,3,2); //读时fenli(2,5,3); //读日fenli(2,3,4); //读月fenli(3,2,5); //读星期fenli(2,1,6); //读年}/*---------------按键处理相关函数--------------------------*//************************************************************ 函数名称:void scanner()功能描述: 按键函数*************************************************************/ void scanner(){ uchar i,j;if(!key) //功能键按下{ delay1ms(500); //延时500MSif(!key) //还按下,退出时间调整{ keyflag=0; //标志位为0sum=0; //清0w_12864(com,0x0c);//清闪烁for(i=0;i<7;i++)//十进制转十六进制{ j=TAB_1302[i]/10;TAB_1302[i]=TAB_1302[i]%10;TAB_1302[i]=TAB_1302[i]+16*j;}init_1302(); //写入1302while(!key); //等待释放delay1ms(10); //延时消抖}else //500MS内放开{ keyflag=1; //标志为1,进行时间调整sum++; //功能键加1if(sum==8)sum=0;switch(sum){ case 1: //{ w_12864(com,0x98+7);w_12864(com,0x0f);break;}case 2: //为2,年闪烁w_12864(com,0x90+1);break;case 3: //月闪烁w_12864(com,0x90+3);break;case 4: //日闪烁w_12864(com,0x90+5);break;case 5: //星期闪烁w_12864(com,0x88+2);break;case 6: //分闪烁w_12864(com,0x88+5);break;case 7: //时闪烁w_12864(com,0x88+3);break;}}}if(sum) //功能键按下{if(!key1){ delay1ms(10);if(!key1){ while(!key1);//等待加1键释放delay1ms(10);if(sum==1){ //备用}if(sum==2){ TAB_1302[6]++;if(TAB_1302[6]==100)TAB_1302[6]=0;fenli(2,1,6);w_12864(com,0x90+1);//闪烁归位}if(sum==3){ TAB_1302[4]++;if(TAB_1302[4]==13)TAB_1302[4]=1;fenli(2,3,4);w_12864(com,0x90+3);}if(sum==4){ TAB_1302[3]++;if(TAB_1302[3]==32)TAB_1302[3]=1;fenli(2,5,3);w_12864(com,0x90+5);}if(sum==5){ TAB_1302[5]++;if(TAB_1302[5]==7)TAB_1302[5]=0;fenli(3,2,5);w_12864(com,0x88+2);}if(sum==6){ TAB_1302[1]++;if(TAB_1302[1]==60)TAB_1302[1]=0;fenli(3,5,1);w_12864(com,0x88+5);}if(sum==7){ TAB_1302[2]++;if(TAB_1302[2]==24)TAB_1302[2]=0;fenli(3,3,2);w_12864(com,0x88+3);}}}}}//============================================================= void init(void){uchar i;init_12864();init_1302();while(TAB1[i]!='\0'){w_12864(dat,TAB1[i]);i++;}i=0;w_12864(com,0x90);while(TAB2[i]!='\0'){w_12864(dat,TAB2[i]);i++;}i=0;w_12864(com,0x88);while(TAB3[i]!='\0'){w_12864(dat,TAB3[i]);i++;}i=0;w_12864(com,0x98);while(TAB4[i]!='\0'){w_12864(dat,TAB4[i]);i++;}}/************************************************************* 函数名称:主函数函数功能:**************************************************************/ main(){init();while(1){scanner(); //检测键盘if(!keyflag) //标志为0{ display(); //调用显示show_T(read_T()); //显示温度delay1ms(500);}}}。
基于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个按键来设定时间。
基于单片机及时钟芯片DS1302的电子时钟设计

基于单片机及时钟芯片DS1302的电子时钟设计一、概述二、电子时钟的基本原理电子时钟是一种以单片机为核心的智能电子产品,采用数字电路来显示时间。
电子时钟的核心部件是一个定时器,通过周期性的计数来确定时间,然后再将计数器的结果通过数码管等显示装置进行显示。
除此之外,电子时钟还需要一个能够准确计时的时钟芯片,如本文所使用的时钟芯片DS1302。
三、电子时钟的设计方法本文设计的电子时钟采用AT89C52单片机和时钟芯片DS1302,并通过外围的驱动电路和数码管来实现时间的显示。
该电子时钟具有以下特点:1.可进行24小时制和12小时制的切换:电子时钟可以通过按键实现24小时制和12小时制的切换,可按需选择。
2.自动夏令时判断:电子时钟可自动识别夏令时,并根据设定值进行切换,方便易用。
3.温度显示:电子时钟的DS1302时钟芯片自带温度探测器,可实现温度的实时显示。
本文所设计的电子时钟的硬件设计方案如下:1.主控芯片:采用AT89C52单片机2.显示装置:采用数码管进行时分秒的显示,共4位数码管。
3.时钟芯片:采用DS1302时钟芯片,保证时间的准确性。
5.电源:采用开关电源或锂电池供电。
锂电池供电时,电子时钟可实现断电后不重置的功能。
1.初始化:在电子时钟启动时,需要对各个模块进行初始化,如DS1302时钟芯片的读写口、数码管和按键都需要进行初始化。
2.频率切换:按下切换按键后,电子时钟的频率从24小时制切换到12小时制。
3.设定夏令时:按下设定按键后,可以进行夏令时设定。
设定值以秒为单位存储,在夏季过渡期改变时,只需修改设定值即可。
5.时间的显示:通过程序将DS1302时钟芯片中的时间读出并在数码管上显示,实现实时显示的功能。
五、总结本文设计的基于单片机及时钟芯片DS1302的电子时钟,可通过按键实现24小时制和12小时制的切换、自动夏令时判断、温度显示等多种功能,实现了电子时钟的多种要求和需求。
该设计方案具有简单实用、成本低廉、易于维护等优点,可广泛应用于各个领域。
DS1302设计的可调万年历(实测正常,附有程序)

DS1302设计的可调万年历(实测正常,附有程序)ds1302设计的可调万年历(本制作所用数码管全为共阳数码管)我刚开始想要搞万年历的时候就是玩游戏打听别人的程序,可是辨认出打听了很多都不理想,必须不就没有日历和时间一起表明,必须不就无法阳入时间的,后来我研究了两天,自己终于把程序编成了出。
不好了,废话我就不多说道,本制作我已经把实物搞了出,确保没问题!下面附有仿真图和实物图。
拍摄的效果不够好,但实物是不错的,本人实物中用三级管代替了仿真图的74hc04非门,用哪个都是可以的……请注意:本程序分后两个c文件的,如果不能编成,可以q我:1107588997我轻易播发程序过去给你……软件源程序:(初始化程序只在已经开始时用一次,之后必须把它屏蔽掉)#include#include#includeuchartime_data[7]={0,0,0,0,0,0,0};ucharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};ucharread_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};voidwrite_ds1302_byte(uchardat){uchari;for(i=0;i<8;i++){sck=0;io=dat&0x01;dat=dat>>1;sck=1;}}voidwrite_ds1302(ucharadd,uchardat){rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);write_ds1302_byte(dat);rst=0;_nop_();io=1;sck=1;}ucharread_ds1302(ucharadd){uchari,value;rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);for(i=0;i<8;i++){value=value>>1;sck=0;if(io)value=value|0x80;sck=1;}rst=0;_nop_();sck=0;_nop_();sck=1;io=1;returnvalue;}voidread_rtc(void){uchari;for(i=0;i<7;i++){time_data[i]=read_ds1302(read_add[i]);}}voidtime_pros(void){nian=time_data[0]/16*10+time_data[0];yue=time_data[2]/16*10+time_data[2];ri=ti me_data[3]/16*10+time_data[3];xi=time_data[1]/16*10+time_data[1];shi=time_data [4]/16*10+time_data[4];fen=time_data[5]/16*10+time_data[5];miao=time_data[6]/1 6*10+time_data[6];}voidmain(){//init_ds1302();//初始化while(1){read_rtc();time_pros();display();button();}}//----------------------------zichengxu.c----------------------------------------------#defineduan1p2#defineduan2p3#defineweip0#defineuintunsignedint#defineucharunsignedcharsbitsck=p1^1;sbitio=p1^0;sbitrst =p1^2;sbitk1=p1^4;sbitk2=p1^5;sbitk3=p1^6;sbitk4=p1^7;ucharshi,fen,miao,nian,yue,ri,xi,menu,y;unsignedcharcodequan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; voidwrite_ds1302_byte(uchardat);voidwrite_ds1302(ucharadd,uchardat);ucharread_ds1302(ucharadd);//voidinit_ds1302(void);//初始化voidread_rtc(void);voidtime_pros(void);voiddisplay(void);voidbutton(void);voiddelay(uintz){ucharx,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/*(voidinit_ds1302(void)//初始化{write_ds1302(0x8e,0x00);write_ds1302(0x80,0x00);write_ds1302(0x82,0x20);write_ ds1302(0x84,0x09);write_ds1302(0x86,0x25);write_ds1302(0x88,0x12);write_ds1302 (0x8a,0x06);write_ds1302(0x8c,0x10);write_ds1302(0x90,0x01);write_ds1302(0xc0, 0xf0);write_ds1302(0x8e,0x80);}*/voiddisplay(void){wei=0;duan1=quan[2];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi/10];delay(2);duan1=0xff;duan2=0xff;wei=1;duan1=quan[0];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi];delay(2);duan1=0xff;duan2=0xff;。
基于时钟日历芯片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 绪论在科技日新月异发展的今天,人们对时间概念的认识显得尤为深刻,“时间就是金钱”,“时间就是生命”等警句更是激励着人们努力工作,把握时间。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<reg52.h>#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;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*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);//定位到星期的位置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();}}。