基于DS1302和LCD1602的万年历闹钟时钟用开发版直接显示的程序副本.docx
《基于DS1302和LCD1602的万年历闹钟时钟用开发版直接显示的程序副本.docx》由会员分享,可在线阅读,更多相关《基于DS1302和LCD1602的万年历闹钟时钟用开发版直接显示的程序副本.docx(13页珍藏版)》请在冰豆网上搜索。
基于DS1302和LCD1602的万年历闹钟时钟用开发版直接显示的程序副本
实时时钟芯片DS1302应用,DS18B20应用实例——可调时钟,LCD1602显示:
(时间+温度)
说明:
需要按程序中定义的接口。
按自己接口,只要在程序中修改接口定义即可。
1、DS1302引脚排列:
如下图
引脚说明:
1)Vcc1:
后备电源,VCC2:
主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:
振荡源,外接32.768kHz晶振。
3)RST:
复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向)。
5)SCLK为时钟输入端。
2、 DS1302的控制字节
DS1302的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见数据手册。
此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:
一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitbeep=P2^3;//闹铃
sbitIO=P1^3;//定义1302管脚
sbitSCLK=P1^4;
sbitRST=P1^5;
sbitRS=P2^2;//定义1602管脚
sbitRW=P2^1;
sbitEN=P2^0;
sbitkey1=P3^4;//选择//调时键盘
sbitkey2=P3^5;//加
sbitkey3=P3^6;//减
sbitkey4=P3^7;//确定
sbitkey11=P1^6;//选择//闹钟键盘
sbitkey22=P1^7;//加
sbitkey33=P3^0;//减
sbitkey44=P3^1;//确定
ucharx1=0,x;
inthour=8,minute=0;//闹钟的初始时间8:
00
ucharDateTime[9];//秒,分,时,日,周,月,年address,
ucharlcd1[]={"Dt2000-00-00"};
ucharlcd2[]={"Time00:
00:
00"};
/***************延时*************/
voiddelayms(ucharx)//延时毫秒程序
{uchari,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/********1302的驱动程序***********/
voidDS1302WriteByte(uchardat)//写入数据,dat:
要写入的数据
{
uchari;
SCLK=0;//初始时钟线置为0
delayms
(2);
for(i=0;i<8;i++)//开始传输8个字节的数据
{
IO=dat&0x01;//取最低位,DS1302的数据和地址都是从最低位开始传输的
delayms
(2);
SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输
delayms
(2);
SCLK=0;//时钟线拉低,为下一个上升沿做准备
dat>>=1;//数据右移一位,准备传输下一位数据
}
}
/********1302的驱动程序**********/
ucharDS1302ReadByte()//功能:
读取数据,dat:
读取的数据
{uchari;
uchardat;
delayms
(2);
for(i=0;i<8;i++)
{
dat>>=1;//要返回的数据左移一位
if(IO==1)//当数据线为高时,证明该位数据为1
dat|=0x80;//要传输数据的当前值置为1,若不是,则为0
SCLK=1;//拉高时钟线
delayms
(1);
SCLK=0;//制造下降沿
delayms
(1);
}
returndat;//返回读取出的数据/16*10+dat%16
}
/*********1302的驱动程序*********///从cmd相应地址中读取一个字节的数据
ucharDS1302Read(ucharcmd)//cmd:
要写入的控制字节,dat:
读取的数据
{
uchardat;
RST=0;//初始CE线置为0
SCLK=0;//初始时钟线置为0
RST=1;//初始CE置为1,传输开始
DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址
dat=DS1302ReadByte();//读取要得到的时间/日期
SCLK=1;//时钟线拉高
RST=0;//读取结束,CE置为0,结束数据的传输
returndat;//返回得到的时间/日期
}
/**********1302的驱动程序*********///向cmd相应地址中写一个字节的数据
voidDS1302Write(ucharcmd,uintdat)//cmd:
要写入的控制字,dat:
要写入的数据
{
RST=0;//初始CE线置为0
SCLK=0;//初始时钟线置为0
RST=1;//初始CE置为1,传输开始
DS1302WriteByte(cmd);//传输命令字,要写入的时间/日历地址
DS1302WriteByte(dat);//写入要修改的时间/日期
SCLK=1;//时钟线拉高
RST=0;//读取结束,CE置为0,结束数据的传输
}
/*************初始化ds1302********///给1302写入日期和时钟的值
voidchushihuaDS1302(void)
{
DS1302Write(0x8e,0x00);//写保护关
DS1302Write(0x80,0x10);//初始秒
DS1302Write(0x82,0x02);//初始分钟
DS1302Write(0x84,0x15);//初始为24小时模式,初始时
DS1302Write(0x86,0x25);//25日
DS1302Write(0x88,0x04);//4月
DS1302Write(0x8c,0x14);//2014年
DS1302Write(0x8a,0x05);//星期5
//DS1302Write(0x90,0x01);//充电
//DS1302Write(0xc0,0xf0);//初始化一次标示
//DS1302Write(0x8e,0x80);//写保护开
}
/************以下是1602的程序******************/
/******************************///向1602内写命令
voidwrite_order(ucharorder)
{
RS=0;
P0=order;
delayms(5);
EN=1;
delayms(5);
EN=0;
}
/******************************///向1602内写数据
voidwrite_date(uchardate)
{
RS=1;
P0=date;
delayms(5);
EN=1;
delayms(5);
EN=0;
}
/******************************///lcd1602的初始化
voidchushihuaLCD1602()
{
EN=0;
write_order(0x38);
write_order(0x0c);
write_order(0x06);
write_order(0x01);
}
/*************其他操作*****************/
voidgettime()
{uchari,n;
for(i=0,n=1;i<7,n<15;i++,n=n+2)
{DateTime[i]=DS1302Read(0x80+n);
delayms
(1);
}
}
voidzhuanhuan()
{gettime();
lcd1[5]=((DateTime[6]>>4)+0x30);
lcd1[6]=((DateTime[6]&0x0f)+0x30);
delayms
(1);//年
lcd1[8]=((DateTime[4]>>4)+0x30);
lcd1[9]=((DateTime[4]&0x0f)+0x30);
delayms
(1);//月
lcd1[11]=((DateTime[3]>>4)+0x30);
lcd1[12]=((DateTime[3]&0x0f)+0x30);
delayms
(1);//日
lcd1[14]=((DateTime[5]>>4)+0x30);
lcd1[15]=((DateTime[5]&0x0f)+0x30);
delayms
(1);//周
lcd2[5]=((DateTime[2]>>4)+0x30);
lcd2[6]=((DateTime[2]&0x0f)+0x30);
delayms
(1);//时
lcd2[8]=((DateTime[1]>>4)+0x30);
lcd2[9]=((DateTime[1]&0x0f)+0x30);
delayms
(1);//分
lcd2[11]=((DateTime[0]>>4)+0x30);
lcd2[12]=((DateTime[0]&0x0f)+0x30);
delayms
(1);//秒
if(DateTime[7]==DateTime[2]&DateTime[8]==DateTime[1])
{
beep=1;
delayms(150);
beep=0;
}/**/
}
/***********************/
voidjianpan()//键盘调时
{ucharx2,address,max,min;
intitem;
if(key1==0)
{delayms(10);
if(key1==0)
{x1++;
if(x1>=7)x1=1;
switch(x1)
{case1:
lcd2[15]='Y';x2=1;address=0x8c;max=99;min=0;break;//年
case2:
lcd2[15]='M';x2=2;address=0x88;max=12;min=1;break;//月
case3:
lcd2[15]='D';x2=3;address=0x86;max=31;min=1;break;//天
case4:
lcd2[15]='H';x2=4;address=0x84;max=23;min=0;break;//时
case5:
lcd2[15]='F';x2=5;address=0x82;max=59;min=0;break;//分
case6:
lcd2[15]='W';x2=6;address=0x8A;max=7;min=1;break;//周
}
}
while(!
key1);
}
item=(DS1302Read(address+1)/16)*10+(DS1302Read(address+1))%16;
if(key2==0)
{delayms(10);
if(key2==0)
{if(x2==1){item++;}
elseif(x2==2){item++;}
elseif(x2==3){item++;}
elseif(x2==4){item++;}
elseif(x2==5){item++;}
elseif(x2==6){item++;}
}
while(!
key2);
}
if(key3==0)
{delayms(10);
if(key3==0)
{if(x2==1){item--;}
elseif(x2==2){item--;}
elseif(x2==3){item--;}
elseif(x2==4){item--;}
elseif(x2==5){item--;}
elseif(x2==6){item--;}
}
while(!
key3);
}
if(key4==0)
{delayms(10);
if(key4==0)
{lcd2[15]='';
x1=0;
x2=0;
}
while(!
key4);
}
//beep=0;delayms(5000);beep=1;
if(item>max)item=min;
if(itemDS1302Write(0x8e,0x00);//允许写操作
delayms(10);
DS1302Write(address,(item/10)*16+item%10);//写入DS1302//转成BCD码
delayms(20);
DS1302Write(0x8e,0x80);//写保护,禁止写操作
}
voidnaozhong()//设定闹钟
{ucharda,xiao,i;
if(key11==0)
{delayms(10);
if(key11==0)
{x++;
if(x>=4)x=1;
switch(x)
{
case2:
lcd2[13]='H';
i=1;da=23;xiao=0;
lcd2[14]=((hour>>4)+0x30);
lcd2[15]=((hour&0x0f)+0x30);
delayms
(1);break;//时
case1:
lcd2[13]='M';
i=2;da=59;xiao=0;
lcd2[14]=((minute>>4)+0x30);
lcd2[15]=((minute&0x0f)+0x30);
delayms
(1);break;//分
case3:
lcd2[13]='';lcd2[14]='';lcd2[15]='';
x=0;i=0;break;
}
}
while(!
key11);
}
if(key22==0)
{delayms(10);
if(key22==0)
{if(i==1)
{hour=((hour/16)*10)+(hour%16);
hour++;
if(hour>da)hour=xiao;
hour=(hour/10)*16+hour%10;
lcd2[14]=((hour>>4)+0x30);
lcd2[15]=((hour&0x0f)+0x30);
delayms
(1);
}
elseif(i==2)
{minute=((minute/16)*10)+(minute%16);
minute++;
if(minute>da)minute=xiao;
minute=(minute/10)*16+minute%10;
lcd2[14]=((minute>>4)+0x30);
lcd2[15]=((minute&0x0f)+0x30);
delayms
(1);
}
}
while(!
key22);
}
if(key33==0)
{delayms(10);
if(key33==0)
{if(i==1)
{hour=((hour/16)*10)+(hour%16);
hour--;
if(hourhour=(hour/10)*16+hour%10;
lcd2[14]=((hour>>4)+0x30);
lcd2[15]=((hour&0x0f)+0x30);
delayms
(1);
}
elseif(i==2)
{minute=((minute/16)*10)+(minute%16);
minute--;
if(minuteminute=(minute/10)*16+minute%10;
lcd2[14]=((minute>>4)+0x30);
lcd2[15]=((minute&0x0f)+0x30);
delayms
(1);
}
}
while(!
key33);
}
DateTime[7]=hour;DateTime[8]=minute;
}/**/
voidwzd0()interrupt0//外部中断0
{
jianpan();//
}
voidwzd1()interrupt2//外部中断1
{
naozhong();
}
voidmain()
{
uchark;
EA=1;EX0=1;IT0=1;PX0=1;
EX1=1;IT1=1;PX1=0;
RW=0;beep=0;
chushihuaLCD1602();
if((DS1302Read(0x81)&0x80))chushihuaDS1302();
//chushihuaDS1302();
while
(1)
{
zhuanhuan();
write_order(0x80);//lcd的第一行
for(k=0;k<16;k++)
{write_date(lcd1[k]);
delayms
(1);
}
write_order(0x80+0x40);//lcd的第二行
for(k=0;k<16;k++)
{write_date(lcd2[k]);
delayms
(1);
}
}
}