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

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

/ZPF(新)//2012//4/29#include <REGX55.H>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar k,s,aa,Nshi,Nfen;//,miao,nian,yue,ri,zhou;uchar number[8];uchar dif_flag;//测温度定义uint temp;float f_temp; //温度值variable of temperature bit flag;sbit w1=P1^2;sbit w2=P1^3;sbit w3=P1^4;sbit w4=P1^5;sbit DQ=P1^7;sbit dula=P1^0;sbit wela=P1^1;sbit DS1302_CLK = P3^7; //实时时钟时钟线引脚sbit DS1302_IO = P3^6; //实时时钟数据线引脚sbit DS1302_RST = P3^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit key=P1^6;sbit key1=P3^0;sbit key2=P3^1;sbit key3=P3^2;sbit key4=P3^3;sbit key5=P3^4;uchar read[7];uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//共阴数码管0-9uchar week_value[2];//void dis_delay(void);void delay(uint x);void display(unsigned char a,unsigned char b,unsigned char c);void show_time(); //显示程序void Write1302(unsigned char ucAddr, unsigned char ucDa);void keyscan();void Display_18b20(uint temp);/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)(4) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)(5) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;//在下降沿数据从移位寄存器输出}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;//只有在clk为低时,才能将rst置高DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;//上升沿将数据写入DS1302内部移位寄存器DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据(3){unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;//启动数据传送DS1302InputByte(ucAddr|0x01); // 地址,命令,读操作(4)ucData = DS1302OutputByte(); // 读1Byte数据,应在上升沿前读取(5)DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void naozhong(uchar x){uchar c = 0;c = 4 * x;Nfen = 0xc1 + c;Nshi = 0xc3 + c;}/***********DS1302按键部分子程序******************/void jia(uchar p, uchar max, uchar com)//p读取时间单位的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p ++;if(p / max)p =0 ;p = (p / 10) * 16 + p % 10;Write1302(com, p);}void jian(uchar p, uchar max, uchar com)//p读取秒的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p --;if(p == 255)p = max ;p = (p / 10) * 16 + p % 10;Write1302(com,p);}void keyscan(){if(!key1){delay(5);if(!key1 ){k++;Write1302(0x8e,0x00);if(k==4)k=0, Write1302(0x8e,0x80);while(!key1);}}if(!key2){delay(5);if(!key2){if(dif_flag == 0){switch(k){case 1:jia(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jia(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jia(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jia(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jia(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jia(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jia(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key2);}}if(!key3){delay(5);if(!key3){if(dif_flag == 0){switch(k){case 1:jian(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jian(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jian(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jian(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jian(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jian(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jian(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key3);}if(key5 ==0);//key5 = 1;}void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组(2){unsigned char ReadV alue;ReadValue = Read1302(DS1302_SECOND);//(3)Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//16进制转为10进制ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadV alue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);}void show_time() //液晶显示程序(1){uchar f=2;DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据(2)read[0]=CurrentTime.Second;read[1]=CurrentTime.Minute;read[2]=CurrentTime.Hour;read[3]=CurrentTime.Week;read[4]=CurrentTime.Day;read[5]=CurrentTime.Month;read[6]=CurrentTime.Year;read[7]=0x00;if(!key){delay(5);if(!key)dif_flag++;while(!key)if(!key5){Write1302(0x8e,0x00);//写写保护寄存器禁止写保护Write1302(0x80,0x00);//写秒Write1302(0x90,0xab);//写充电寄存器Write1302(0x82,0x00);//分Write1302(0x84,0x12);//时Write1302(0x86,0x01);//日Write1302(0x88,0x05);//月Write1302(0x8a,0x02);//周Write1302(0x8c,0x12);//年Write1302(0x8e,0x80);//写保护}}}if(dif_flag==3)dif_flag=0;for(f=2;f>0;f--){if(dif_flag==0)display(read[0],read[1],read[2]);else if(dif_flag==1)display(read[4],read[5],read[6]);else if(dif_flag==2)display(read[3],read[7],read[7]);}}//显示延时函数void dis_delay(uchar x){uchar i;for(i=0;i<x;i++);}void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}/*****************DS18B20******************/void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command {uint i;DQ = 0; //单片机拉低总线i=70;while(i>0)i--;DQ = 1; //释放总线,即拉高了总线i=4;while(i>0)i--;}bit Read_One_bit() //读取一个字节的数据read a byte date//读数据时,数据以字节的最低有效位先从总线移出{uint i;bit dat;DQ=0;i++;DQ=1;i++;i++;dat=DQ;i=5;while(i>0)i--;return (dat);}uchar Read_One_Byte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=Read_One_bit();dat=(j<<7)|(dat>>1);}return (dat);}void Write_One_Byte(uchar dat){uint i;uchar j;bit testb;show_time();for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DQ=0;i++;i++;DQ=1;i=5;while(i>0)i--;}else{DQ=0;i=5;while(i>0)i--;DQ=1;i++;i++;}}}void tmpchange(void){uchar f;Init_Ds18b20();f=70;while(f>0)f--;Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0x44); //温度转换指令}uint Get_Tmp() //获取温度get the temperature{uchar a,b,f;Init_Ds18b20(); //初始化f=70;while(f>0)f--;show_time();Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0xbe); //温度转换指令a = Read_One_Byte(); //读取到的第一个字节为温度LSBb = Read_One_Byte(); //读取到的第一个字节为温度MSBshow_time();if(b>127){flag=1;a=~a;b=~b;a+=0x01;}else{flag=0;}temp = b; //先把高八位有效数据赋于temptemp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量f_temp = temp*0.0625; ////temp = (f_temp*10+0.5)*0.9; //放大十倍//0.9调试加上理论不需要temp = f_temp*10+0.5;//f_temp=f_temp+0.5; // //同时进行一个四舍五入操作。
基于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万年历

#define DS1302_IO_HIGH io_DS1302_IO = 1 ;
#define DS1302_IO_LOW io_DS1302_IO = 0 ;
#define DS1302_IO_READ io_DS1302_IO
sbit key4=P3^3; //减
sbit key5=P3^4; //返回
int main_flag=0;//,exit_flag,up_flag,down_flag;
void Time0_int()
{
TMOD=0X01;
TH0=0XF8; //@11.0592MHz 定时2ms
/*****************************************************************************
功能:显示时间日期万年历。上电显示时间,格式:小时-分钟-秒。
按下key1显示日期,格式:月-天-星期
按下key2调节闪烁位置,进行更改时间操作
#define KEY_PRESS 0x80 //1000 0000
#define KEY_LONG 0x40 //0100 0000
#define KEY_STATE_INIT 0
#define KEY_STATE_PRESS 1
#define KEY_STATE_LONG 2
#define DS1302_WEEK_WRITE 0x8A
#define DS1302_DAY_WRITE 0x86
#define DS1302_MONTH_WRITE 0x88
#define DS1302_YEAR_WRITE 0x8C
基于单片机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设计的可调万年历(实测正常,附有程序)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 绪论在科技日新月异发展的今天,人们对时间概念的认识显得尤为深刻,“时间就是金钱”,“时间就是生命”等警句更是激励着人们努力工作,把握时间。
基于DS1302的万年历

基于DS1302的万年历(N个数码管显示)2009-06-11 18:49#include <reg51.h>code unsigned char key_code[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0x88,0x83,0xc6,0xa1,0x86,0x 8e,0xff};unsigned int code TAB1[13]={0,0,31,59,90,120,151,181,212,243,273,304,334};unsigned int code TAB2[13]={0,0,31,60,91,121,152,182,213,244,274,305,335};unsigned char sec,min,hour,day,week,month,year,moth;old_day,old_month;unsigned char w=0,led[19],typ,l_day,h_day;unsigned char DS1302_ADDR _at_ 0x32;unsigned char DS1302_DA TA _at_ 0x31;unsigned char outkey _at_ 0x70;unsigned char tt=0;bit sett=1,g,h=0,leap;//读void read(){#pragma asmCLR P2.7NOPNOPSETB P2.5NOPMOV A,32HMOV R4,#08HREAD1:RRC ANOPMOV P2.6,CNOPNOPNOPSETB P2.7NOPNOPNOPCLR P2.7NOPNOPDJNZ R4,READ1MOV R4,#08HREAD2:CLR P2.7NOPNOPNOPMOV C,P2.6NOPNOPNOPNOPNOPRRC ANOPNOPNOPNOPSETB P2.7NOPDJNZ R4,READ2MOV 31H,ACLR P2.5#pragma endasm}//写void write(){#pragma asmCLR P2.7NOPSETB P2.5NOPMOV A,32HMOV R4,#8WRITE1:RRC ANOPNOPCLR P2.7NOPNOPNOPMOV P2.6,CNOPNOPNOPSETB P2.7NOPNOPDJNZ R4,WRITE1CLR P2.7NOPMOV A,31HMOV R4,#8WRITE2:RRC ANOPCLR P2.7NOPNOPMOV P2.6,CNOPNOPNOPSETB P2.7NOPNOPDJNZ R4,WRITE2CLR P2.5#pragma endasm}//延时void delay(void){unsigned char i,j;for(i=0;i<5;i++)for(j=0;j<255;j++);}//读键unsigned char got_key(){ unsigned char ks_1,ks_2;ks_1=~P1;ks_1=(ks_1&0x0f);//保留p1.0/p1.1/p1.2/p1.3 delay();ks_2=~P1;ks_2=(ks_2&0x0f);//保留p1.0/p1.1/p1.2/p1.3 if(ks_1==ks_2) return(ks_1);else return(0);}//输出void outof(){#pragma asmMOV A,70HMOV R4,#8OUT_1:RRC AACALL DELCLR P3.1ACALL DELMOV P3.0,CACALL DELSETB P3.1ACALL DELDJNZ R4,OUT_1SJMP OUT_2DEL: MOV R1,#30DJNZ R1,$RETOUT_2:#pragma endasm}//更新void newh_1(unsigned char *p){ DS1302_ADDR=0x8d;//年read();p[0]=DS1302_DA TA;DS1302_ADDR=0x8b;//星期read();p[1]=DS1302_DA TA;DS1302_ADDR=0x89;//月read();p[2]=DS1302_DA TA;DS1302_ADDR=0x87;//日read();p[3]=DS1302_DA TA;}void newh(){unsigned char i,new_1[4],new_2[4];while(i<4){newh_1(new_1);delay();newh_1(new_2);for(i=0;i<4;i++) {if(new_1[i]!=new_2[i]) break;} }year=new_1[0];week=new_1[1];month=new_1[2];day=new_1[3];}void newl(){ DS1302_ADDR=0x85;//时read();hour=DS1302_DATA;DS1302_ADDR=0x83;//分read();min=DS1302_DATA;DS1302_ADDR=0x81;//秒read();sec=DS1302_DATA;}void newd_1(unsigned char *p)//更新安全天数{ DS1302_ADDR=0xc7;read();p[0]=DS1302_DA TA;DS1302_ADDR=0xc9;read();p[1]=DS1302_DA TA;DS1302_ADDR=0xcb;read();p[2]=DS1302_DA TA;DS1302_ADDR=0xcd;read();p[3]=DS1302_DA TA;}void newd(){unsigned char i,new_1[4],new_2[4];while(i<4){newd_1(new_1);delay();newd_1(new_2);for(i=0;i<4;i++) {if(new_1[i]!=new_2[i]) break;} }l_day=new_1[0];h_day=new_1[1];old_day=new_1[2];old_month=new_1[3];}//数据存储void updata(){DS1302_ADDR=0x8e;DS1302_DATA=0x00;//允许写入write();DS1302_ADDR=0x8c;DS1302_DATA=year;//写入年write();DS1302_ADDR=0x88;DS1302_DATA=month;//写入月write();DS1302_ADDR=0x86;DS1302_DATA=day;//写入日write();DS1302_ADDR=0x8a;DS1302_DATA=week;//写入星期write();DS1302_ADDR=0x84;DS1302_DATA=hour;//写入时write();DS1302_ADDR=0x82;DS1302_DATA=min;//写入分write();DS1302_ADDR=0x80;DS1302_DATA=sec;//写入秒write();DS1302_ADDR=0x8e;DS1302_DATA=0x80;//禁止写入write();}void updatad()//写入安全天数{DS1302_ADDR=0x8e;DS1302_DATA=0x00;//允许写入write();DS1302_ADDR=0xc6;DS1302_DATA=l_day;write();DS1302_ADDR=0xc8;DS1302_DATA=h_day;write();DS1302_ADDR=0xca;DS1302_DATA=day;write();DS1302_ADDR=0xcc;DS1302_DATA=month;write();DS1302_ADDR=0x8e;DS1302_DATA=0x80;//禁止写入write();}//中断显示void out() interrupt 1{unsigned char i;TR0=0;TH0=0x3c;TL0=0xb0;TR0=1;tt=tt+1;if(tt==10) g=1;if(tt>=20) {tt=0;g=0;typ+=1;}if(sett){newl();if(sec!=0) h=0;if (hour==0&&min==0&&sec==0&&!h){newh();l_day+=1;if(l_day==100){l_day=0;h_day+=1;}h=1;updatad();}}led[0]=l_day%10;led[1]=l_day/10;led[2]=h_day%10;led[3]=h_day/10;led[4]=hour/16;led[5]=hour%16;led[6]=2;led[7]=0;led[8]=year/16;led[9]=year%16;led[10]=month/16;led[11]=month%16;led[12]=day/16;led[13]=day%16;led[14]=min/16;led[15]=min%16;led[16]=sec/16;led[17]=sec%16;led[18]=week;for(i=0;i<19;i++){if (!sett && h && !g && ((w==7 && (i<4))||(w==6 && (i==6||i==7||i==8||i==9))||(w==5 && (i==10||i==11))||(w==4 && (i==12||i==13))||(w==3 && (i==4||i==5))||(w==2 &&(i==14||i==15))||(w==1 && (i==16||i==17)))) outkey=key_code[16];else outkey=key_code[led[i]];outof();}#pragma asmCLR P3.5NOPNOPSETB P3.5#pragma endasm}//判断闰年void judge_year(unsigned char x){unsigned int y=2000+x;if((y%4==0&&y%100!=0)||(y%400==0))leap=1;elseleap=0;}//计算星期void weekday(){ unsigned char temp,i=0,j=0,mon;for(temp=0;temp<(year/16*10+year%16);temp++){ judge_year(temp);if(leap==1)i+=1;elsej+=1;}mon=month/16*10+month%16;judge_year(year/16*10+year%16);if(leap==1)week=((i*366+j*365+ TAB2[mon]+(day/16*10+day%16-1))%7+6)%7;elseweek=((i*366+j*365+ TAB1[mon]+(day/16*10+day%16-1))%7+6)%7;if(week==0) week=7;}//时钟设置void switch_add(){switch(w){case 6:year+=1;if(year%16==10) year=year+6;if(year/16==10) year=0;judge_year(year);break;case 5:month+=1;if(month%16==10) month=month+6;if(month>=19) month=1;break;case 4:day+=1;if(day%16==10) day=day+6;if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==16)||(month==18)) moth=1;else if((month==4)||(month==6)||(month==9)||(month==17)) moth=2;else moth=0;switch(moth){case 0:if(leap==0){if(day>=41) day=1;}elseif(day>=48) day=1;break;case 1:if(day>=50) day=1;break;case 2:if(day>=49) day=1;break;default:break;}break;case 3:hour+=1;if(hour%16==10) hour=hour+6;if(hour>=36) hour=0;break;case 2:min+=1;if(min%16==10) min=min+6;if(min>=96) min=0;break;case 1:sec+=1;if(sec%16==10) sec=sec+6;if(sec>=96) sec=0;break;default:break;}}void switch_sub(){ switch(w){case 6:year-=1;if(year%16>=10) year=year-6;if(year>=154) year=153;judge_year(year);break;case 5:month-=1;if(month%16>=10) month=month-6;if(month==0) month=18;break;case 4:day-=1;if(day%16>=10) day=day-6;if(day==0){if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==16)||(month==18)) moth=1;else if((month==4)||(month==6)||(month==9)||(month==17)) moth=2;else moth=0;switch(moth){case 0:if(leap==0) day=40;else day=41;break;case 1:day=49;break;case 2:day=48;break;default:break;}}break;case 3:hour-=1;if(hour%16>=10) hour=hour-6;if(hour>=36) hour=35;break;case 2:min-=1;if(min%16>=10) min=min-6;if(min>=96) min=89;break;case 1:sec-=1;if(sec%16>=10) sec=sec-6;if(sec>=96) sec=89;break;default:break;}}void set1(){unsigned char key;w=6;while(w>0){h=1;key=got_key();if(key==1) {w=0;while (key!=0) key=got_key();}if(key==2) {--w;while (key!=0) key=got_key();}if(key==4){switch_add();typ=0;while (key!=0){key=got_key();if(typ>=2){h=0;while (key!=0){if(key==4 && tt%5==0) {switch_add();while (tt%5==0);}key=got_key();}}}}if(key==8){switch_sub();typ=0;while (key!=0){key=got_key();if(typ>=2){h=0;while (key!=0){if(key==8 && tt%5==0) {switch_sub();while (tt%5==0);}key=got_key();}}}}}weekday();updatad();sett=1;}//安全天数设置day_add(){l_day+=1;if(l_day>=100){l_day=0;h_day+=1;}if(h_day>=100) h_day=0;}day_sub(){l_day-=1;if(l_day>=100){l_day=99;h_day-=1;}if(h_day>=100) h_day=99;}void set_d(){unsigned char key;sett=0;w=7;w=7;h=1;h=1;while (key!=0) key=got_key();while(w>6){h=1;key=got_key();if(key==1) {w=0;while (key!=0) key=got_key();}if(key==2) {l_day=0;h_day=0;while (key!=0) key=got_key();}if(key==4){day_add();typ=0;while (key!=0){key=got_key();if(typ>=2){h=0;while (key!=0){if(key==4 && tt%5==0) {day_add();while (tt%5==0);}key=got_key();}}}if(key==8){day_sub();typ=0;while (key!=0){key=got_key();if(typ>=2){h=0;while (key!=0){if(key==8 && tt%5==0) {day_sub();while (tt%5==0);}key=got_key();}}}}}updatad();sett=1;}//主程序void main(){unsigned char key;unsigned int num_1,num_2;delay();delay();newl();newl();newh();newh();newd();newd();judge_year(year/16*10+year%16);if(leap==1){num_1=(TAB2[month]+(day/16*10+day%16-1));num_2=(TAB2[old_month]+(old_day/16*10+old_day%16-1)); }else{num_1=(TAB1[month]+(day/16*10+day%16-1));num_2=(TAB1[old_month]+(old_day/16*10+old_day%16-1)); }h_day=(num_1-num_2)/100+h_day;l_day=(num_1-num_2)%100+l_day; updatad();SCON=0;IE=0x82;TMOD=0x01;TH0=0xfc;TL0=0x18;TR0=1;while(1){key=got_key();if(key==1){typ=0;while (key!=0){key=got_key();if(typ>=4) {sett=0;set_d();}}}if(key==2){sett=0;while (key!=0) key=got_key();set1();}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
广东交通职业技术学院毕业论文毕业论文题目:基于DS1302与数码管设计的电子万年历学生姓名:***学号:**********院(系):机电工程学院专业:机电一体化(自动化技术)班级:一体化123班指导教师:**起止时间:2014 年11 月—— 2014 年 12 月基于DS1302与数码管设计的电子万年历摘要:单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及我们生活中广泛使用的各种智能IC卡、电子产品等,这些都离不开单片机。
单片机是将CPU、RAM、ROM、定时器、计数器和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上,而51系列单片机是各单片机中最为典型和最有代表性的一种。
本文通过对一个基于DS1302与数码管的电子万年历的设计,从而达到学习、了解单片机相关指令在各方面的应用。
系统由主控制器AT89C51、实时钟电路DS1302、显示电路组成,能实现时钟日历显示的功能,能进行时、分、秒的显示。
关键词:单片机;DS1302;数码管;电子万年历目录1引言 (4)2 设计方案与要求 (4)2.1 功能要求 (4)2.2 系统基本方案选择和论证 (4)2.2.1单片机芯片的选择和论证 (4)2.2.2显示模块的选择和论证 (5)2.2.3时钟芯片的选择和论证 (5)2.3 电路设计最终方案决定 (5)2.4 各硬件基本原理及介绍 (5)2.4.1AT89C51单片机原理及介绍 (5)2.4.2LED数码管显示原理及介绍 (6)2.4.3DS1302原理及介绍 (6)2.4.474HC573原理及介绍 (7)3 硬件设计部分 (7)3.1 电路设计框图 (7)3.2 系统硬件概述 (7)3.3 主要单元电路的设计 (8)3.3.1单片机主控制模块的设计 (8)3.3.2时钟电路DS1302的设计 (8)3.3.3显示模块的设计 (10)3.3.4锁存器模块的设计 (11)4软件设计部分 (11)4.1 软件设计概述 (11)4.2 Keil C51和Proteus介绍 (12)4.2.1Keil C51的介绍 (12)4.2.2Proteus的介绍 (12)4.3 整体设计 (12)5结束语 (14)1 引言随着微电子技术的高速发展,随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
单片机以体积小、功能全、性价比高等诸多优点,在工业控制、家用电器、通信设备、信息处理、尖端武器等各种测控领域的应用中独占鳌头,单片机开发技术已成为电子信息、电气、通信、自动化、机电一体化等专业技术人员必须掌握的技术。
而电子万年历作为电子类小设计,是单片机实验中一个很常用的题目。
因为它有很好的开放性和可发挥性,不仅考察了对单片机的掌握能力更加强了对单片机扩展的应用。
而且在操作的设计上要力求简洁,功能上尽量齐全,显示界面也要出色。
电子万年历已经越来越流行,特别是适合在家庭居室、办公室、大厅、会议室、车站和广场等使用,壁挂式LED数码管显示的万年历逐渐受到人们的欢迎。
采用软件和硬件结合的方法,控制LED数码管输出,分别用来显示年、月、日、时、分、秒,其最大特点是:硬件电路简单,安装方便易于实现,软件设计独特可靠。
在软件设计过程中,应对硬件部分有相关的了解,这样有助于对设计更深刻的了解,有助于软件设计。
2 设计方案与要求2.1 功能要求本电子万年历的功能:能动态显示年、月、日、小时、分钟、秒2.2 系统基本方案选择和论证2.2.1单片机芯片的选择和论证方案一:采用AT89S52芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。
方案二:采用AT89C51,片内ROM全都采用Flash ROM;能以3V的超底压工作;同时也与MCS-51系列单片机完全该芯片内部存储器为8KB ROM 存储空间,同样具有89S52的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要对芯片多次拔插,所以不会对芯片造成损坏。
结论:采用AT89C51作为主控制系统.2.2.2显示模块的选择和论证方案一:采用LED液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字、图形。
但是价格昂贵,需要的接口线多,所以在此设计中不采用LED液晶显示屏。
方案二:采用LED数码管动态扫描,LED数码管价格适中,对于显示数字最合适,而且采用动态扫描法与单片机连接时,占用的单片机口线少。
结论:采用LED数码管作为显示。
2.2.3时钟芯片的选择和论证方案一:直接采用单片机定时计数器提供脉冲信号,使用程序实现年、月、日、时、分、秒计数。
采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。
方案二:采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动对秒、分、时、月、年进行计数,而且精度高。
结论:采用DS1302作为时钟芯片。
2.3 电路设计最终方案决定综上各方案所述,对此次作品的方案选定: 采用AT89C51作为主控制系统、DS1302提供时钟、LED数码管动态扫描作为显示。
2.4 各硬件基本原理及介绍2.4.1 AT89C51单片机原理及介绍单片机是一种集成电路芯片,是采用超大规模集成电路技术把CPU、随机存储器RAM、ROM、多种I/O接口和中断系统、定时器/计数器、A/D转换器等功能集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。
AT89C51单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3, MCS-51单片机共有4个8位的I/O 口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
AT89C51引脚如图所示2.4.2LED数码管显示原理及介绍LED显示是绝大多数单片机应用系统必备的部件之一,发光二极管组成的LED显示是单片机应用产品中最常用的廉价输出设备。
它由若干个发光二极管按一定的规律排列而成。
当某一个发光二极管导通时,相应的一个点或一笔画被点亮,控制不同组合的二极管导通,就能显出各种字符。
发光二极管的阳极连在一起的称为共阳极显示器,阴极连在一起的成为共阴显示器。
1位显示器由8个发光二极管组成,其中7个发光二极管a~g控制7个笔画的亮或暗,另一个控制一个小数点的亮和暗。
引脚如图所示2.4.3DS1302原理及介绍DS1302是美国DALLAS公司推出的一种高性能、低功耗的电子万年历芯片,附加31字节静态RAM,采用SPI三线接口与CPU一进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。
电子万年历可提供秒、分、时、日、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5V~5.5V。
采用双电源供电(主电源和备用电源)。
DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
引脚如图所示2.4.4 74HC573原理及介绍当锁存使能端LE 为高时,这些器件的锁存对于数据是透明的,当锁存使能端LE 为低时,符合建立时间和保存时间的数据会被锁存。
引脚如图所示3 硬件设计部分3.1 电路设计框图3.2 系统硬件概述本设计是由AT89C51单片机为控制核心,具有在线编程功能,低功耗,能在3V 超低压工作。
时钟电路由DS1302提供,采用三线接口与CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM 数据。
具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能,本电路采用DS1302单字节传送方式实现与主控机之间数据的传送。
显示部分由LED 数码管动态扫描来显示。
时钟电路 DS1302主控制器 AT89C51 显示电路 LED 数码管3.3 主要单元电路的设计3.3.1单片机主控制模块的设计单片机的最小系统如下图所示,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端为输入端,XTAL2接外部晶振和微调电容的另一端为输出端。
第9引脚为复位输入端,接上电容,电阻及开关后构成复位电路。
主控制系统1.内部结构按功能分为8部分:CUP,程序存储器,数据存储器,时钟电路,串行口,并行I/O口,中断系统,定时/计数器。
2.引脚定义及功能Vcc:接+5V 电源Vss:接地XTAL1和XTAL2:时钟引脚,外接晶体引线端。
RST/Vpq:RST是复位信号输入端,Vpd是备用电源输入端。
I/O口引脚:P0.0~P0.7:P0口8位双向I/O口;P1.0~P1.7:P1口8位准双向I/O口;P2.0~P2.7:P2口8位准双向I/O口;P3.0~P3.7:P3口8位准双向I/O口。
3.3.2时钟电路DS1302的设计1.引脚功能及结构DS1302 的电路图如下,其中Vcc1 为后备电源,VCC2 为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302 由Vcc1 或Vcc2 两者中的较大者供电。
X1 和X2 是振荡源,外接32.768kHz 晶振。
RST 是复位/片选线,通过把RST 输入驱动置高电平来启动所有的数据传送。
RST 输入有两种功能:首先,RST 接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST 提供终止单字节或多字节数据的传送手段。
只有在SCLK 为低电平时,才能将RST 置为高电平。
I/O 为串行数据输入输出端(双向), SCLK 始终是输入端。
DS1302与单片机的连接也仅需要3条线:CE引脚、SCLK串行时钟引脚、I/O串行数据引脚。
DS1302电路图2.读写时序说明DS 1302是SPI总线驱动方式。
它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。
DS1302的控制字如图:DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲。
控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0则表示存取日历时钟数据,为1表示存取RAM数据位5至位1(A4-A0):指示操作单元的地址位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。