52+ds1302+LCD1602+DS18B20万年历.docx
《52+ds1302+LCD1602+DS18B20万年历.docx》由会员分享,可在线阅读,更多相关《52+ds1302+LCD1602+DS18B20万年历.docx(20页珍藏版)》请在冰豆网上搜索。
![52+ds1302+LCD1602+DS18B20万年历.docx](https://file1.bdocx.com/fileroot1/2023-1/1/4588675c-5542-4f5b-a9a3-78f57174682b/4588675c-5542-4f5b-a9a3-78f57174682b1.gif)
52+ds1302+LCD1602+DS18B20万年历
/****************************************************
*能实现年月日、时分秒、星期的显示及温度的采集,其*
*中设置了三个按钮用于修改时间*
*****************************************************/
#include
#include"intrins.h"
#defineucharunsignedchar
#defineuintunsignedint
ucharcodenyr[]={"20--"};
ucharcodehms[]={":
:
."};
ucharcodeset1302[]={0x00,0x00,0x12,0x09,0x08,0x02,0x12};
ucharnian,yue,ri,shi,fen,miao,week,s1num=0,flag=0;
inttemper;
sbitDQ=P3^7;
sbitds1302_rst=P2^5;
sbitds1302_io=P2^7;
sbitds1302_sclk=P2^6;
sbitlcd1602_rs=P2^0;
sbitlcd1602_rw=P2^1;
sbitlcd1602_e=P2^2;
sbits1=P3^0;
sbits2=P3^1;
sbits3=P3^2;
//LCD延时
voiddelay(ucharz)
{
ucharx,y;
for(x=z;z>0;z--)
for(y=110;y>0;y--);
}
//温度延时
voiddelay2(uinttemp)
{
uinti,j;
for(i=0;ifor(j=0;j<1;j++);
}
/************DS1302****************/
//DS1302写操作命令
voidwrite_byte(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
ds1302_sclk=0;
ds1302_io=dat&0x01;
dat=dat>>1;
ds1302_sclk=1;
}
}
//向DS1302的某个地址写入数据
voidds1302_write(ucharadd,uchardate)
{
ds1302_rst=0;
ds1302_sclk=0;
ds1302_rst=1;
write_byte(add);
write_byte(date);
ds1302_sclk=1;
ds1302_rst=0;
}
//读取DS1302的某地址的数据
uchards1302_read(ucharadd)
{
uchari,value;
ds1302_rst=0;
_nop_();
ds1302_sclk=0;
_nop_();
ds1302_rst=1;
_nop_();
write_byte(add);
for(i=0;i<8;i++)
{
value=value>>1;
ds1302_sclk=0;
if(ds1302_io)
value=value|0x80;
ds1302_sclk=1;
}
ds1302_rst=0;
_nop_();
ds1302_sclk=0;
_nop_();
ds1302_sclk=1;
ds1302_io=1;
returnvalue;
}
//初始化ds1302的时间
voidwrite_set1302()
{
uchari;
ucharaddr=0x80;
ds1302_write(0x8e,0x00);//控制命令WP=0,写操作
for(i=0;i<7;i++)
{
ds1302_write(addr,set1302[i]);//写入数据
addr+=2;
}
ds1302_write(0x8e,0x80);//控制命令WP=1,写保护
}
//DS1302的初始化
voidds1302_init()
{
ds1302_rst=0;
ds1302_sclk=1;
ds1302_write(0x8e,0x80);//写保护
}
/***************LCD1602*****************/
//LCD1602写命令函数
voidlcd_write_com(ucharcom)
{
lcd1602_rw=0;
_nop_();
lcd1602_rs=0;
_nop_();
P0=com;
_nop_();
lcd1602_e=1;
_nop_();
lcd1602_e=0;
_nop_();
lcd1602_rw=1;
delay(5);
}
//LCD1602写数据函数
voidlcd_write_date(uchardate)
{
lcd1602_rw=0;
_nop_();
lcd1602_rs=1;
_nop_();
lcd1602_e=1;
_nop_();
P0=date;
_nop_();
lcd1602_e=0;
_nop_();
lcd1602_rw=1;
delay(5);
}
//设定LCD显示位置
voidlcd_pos(uchary,ucharx)
{
uchara;
if(y==1)
a=0x80+x;//第一行位码
if(y==2)
a=0xc0+x;//第二行位码
lcd_write_com(a);//写入数据
}
//LCD固定字符的显示
voidlcd1602_set()
{
uchari;
lcd_pos(1,0);
for(i=0;i<8;i++)
{
lcd_write_date(nyr[i]);
delay
(2);
}
lcd_pos(2,0);
for(i=0;i<14;i++)
{
lcd_write_date(hms[i]);
delay
(2);
}
lcd_pos(2,14);
for(i=14;i<16;i++)
{
lcd_write_date(0xdf);
lcd_write_date('C');
delay(5);
}
}
//LCD1602初始化
voidlcd1602_init()
{
lcd_write_com(0x38);//8位数据,双列,5*7字形
lcd_write_com(0x0c);//开启显示屏,显示光标,光标不闪烁
lcd_write_com(0x06);//写一个数据后,显示位置(光标)右移一位,显示屏不移动
lcd_write_com(0x01);//清屏
}
/************DS18B20*************/
//DS18B20初始化
ucharreset()
{
ucharpresence;
DQ=0;
delay2(29);
DQ=1;
delay2(3);
presence=DQ;
delay2(25);
return(presence);
}
//读DS18B20一位数据
ucharread_bit()
{
uchari;
DQ=0;
DQ=1;
for(i=0;i<3;i++);
return(DQ);
}
//写DS18B20一位数据
voidwrite_bit(uchardate)
{
DQ=0;
if(date==1)
DQ=1;
delay2(5);
DQ=1;
}
//读DS18B20一字节数据
ucharread_byte1()
{
uchardate=0;
uchari;
for(i=0;i<8;i++)
{
if(read_bit())
date|=0x01<
delay2
(1);
}
return(date);
}
//写DS18B20一字节数据
voidwrite_byte1(uchardate)
{
uchari,j;
for(i=0;i<8;i++)
{
j=((date>>i)&0x01);
write_bit(j);
delay2
(1);
}
}
//读取温度
intread_temp()
{
uchartempl,temph;
inttemp;
reset();
write_byte1(0xcc);
write_byte1(0x44);
delay2(10000);
reset();
write_byte1(0xcc);
write_byte1(0xbe);
templ=read_byte1();
temph=read_byte1();
temp=temph;
temp<<=8;//两个字节组合为1个字节
temp=temp|templ;
temp=temp*0.0625*10;
return(temp);
}
/**************显示部分*****************/
//年月日时分秒的显示
voidwrite_display(uchardate)
{
ucharshi,ge;
shi=date/10;
ge=date%10;
lcd_write_date(0x30+shi);
lcd_write_date(0x30+ge);
}
//BCD转化成十进制
ucharBCDtoDec(ucharbcd)
{
ucharc;
c=((bcd&0xf0)>>4)*10+(bcd&0x0f);
return(c);
}
//十进制转化成BCD
ucharDectoBCD(uchardec)
{
uchari;
i=dec/10;
dec=dec%10;
dec=i*16+dec;
return(dec);
}
//显示星期的子函数
voidwrite_week(ucharwe)
{
switch(we)
{
case1:
lcd_write_date('M');
lcd_write_date('o');
lcd_write_date('n');
break;
case2:
lcd_write_date('T');
lcd_write_date('u');
lcd_write_date('e');
break;
case3:
lcd_write_date('W');
lcd_write_date('e');
lcd_write_date('d');
break;
case4:
lcd_write_date('T');
lcd_write_date('h');
lcd_write_date('u');
break;
case5:
lcd_write_date('F');
lcd_write_date('r');
lcd_write_date('t');
break;
case6:
lcd_write_date('S');
lcd_write_date('a');
lcd_write_date('t');
break;
case7:
lcd_write_date('S');
lcd_write_date('u');
lcd_write_date('n');
break;
}
}
/*************按键设置*****************/
voidkeyscan()
{
if(s1==0)
{
delay(5);
if(s1==0)
{
flag=1;
s1num++;
while(!
s1);//检测按键是否放开
if(s1num==1)
{
lcd_pos(1,3);
lcd_write_com(0x0f);
}
if(s1num==2)
{
lcd_pos(1,6);
}
if(s1num==3)
{
lcd_pos(1,9);
}
if(s1num==4)
{
lcd_pos(1,14);
}
if(s1num==5)
{
lcd_pos(2,1);
}
if(s1num==6)
{
lcd_pos(2,4);
}
if(s1num==7)
{
lcd_pos(2,7);
}
if(s1num==8)
{
s1num=0;
lcd_write_com(0x0c);
flag=0;
ds1302_write(0x8e,0x00);//写允许
ds1302_write(0x80,DectoBCD(miao));//初始秒
ds1302_write(0x82,DectoBCD(fen));//初始分
ds1302_write(0x84,DectoBCD(shi));//初始时
ds1302_write(0x86,DectoBCD(ri));//初始日
ds1302_write(0x88,DectoBCD(yue));//初始月
ds1302_write(0x8a,DectoBCD(week));//初始周
ds1302_write(0x8c,DectoBCD(nian));//初始年
ds1302_write(0x8e,0x80);//写保护
}
}
}
if(s1num!
=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!
s2);
if(s1num==7)
{
miao++;
if(miao==60)
miao=0;
lcd_pos(2,6);
write_display(miao);
lcd_pos(2,7);
}
if(s1num==6)
{
fen++;
if(fen==60)
fen=0;
lcd_pos(2,3);
write_display(fen);
lcd_pos(2,4);
}
if(s1num==5)
{
shi++;
if(shi==24)
shi=0;
lcd_pos(2,0);
write_display(shi);
lcd_pos(2,1);
}
if(s1num==4)
{
week++;
if(week==8)
week=1;
lcd_pos(1,12);
write_week(week);
lcd_pos(1,14);
}
if(s1num==3)
{
ri++;
if(ri==32)
ri=0;
lcd_pos(1,8);
write_display(ri);
lcd_pos(1,9);
}
if(s1num==2)
{
yue++;
if(yue==13)
yue=1;
lcd_pos(1,5);
write_display(yue);
lcd_pos(1,6);
}
if(s1num==1)
{
nian++;
if(nian==100)
nian=0;
lcd_pos(1,2);
write_display(nian);
lcd_pos(1,3);
}
}
}
}
if(s1num!
=0)
{
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!
s3);
if(s1num==7)
{
miao--;
if(miao==-1)
miao=59;
lcd_pos(2,6);
write_display(miao);
lcd_pos(2,7);
}
if(s1num==6)
{
fen--;
if(fen==-1)
fen=59;
lcd_pos(2,3);
write_display(fen);
lcd_pos(2,4);
}
if(s1num==5)
{
shi--;
if(shi==-1)
shi=23;
lcd_pos(2,0);
write_display(shi);
lcd_pos(2,1);
}
if(s1num==4)
{
week--;
if(week==0)
week=7;
lcd_pos(1,12);
write_week(week);
lcd_pos(1,14);
}
if(s1num==3)
{
ri--;
if(ri==0)
ri=31;
lcd_pos(1,8);
write_display(ri);
lcd_pos(1,9);
}
if(s1num==2)
{
yue--;
if(yue==0)
yue=12;
lcd_pos(1,5);
write_display(yue);
lcd_pos(1,6);
}
if(s1num==1)
{
nian--;
if(nian==-1)
nian=99;
lcd_pos(1,2);
write_display(nian);
lcd_pos(1,3);
}
}
}
}
}
//液晶显示内容
voidLCD1602display()
{
if(flag==0)//判断无按键按下
{
//读取秒分时,日月年,星
miao=BCDtoDec(ds1302_read(0x81));
fen=BCDtoDec(ds1302_read(0x83));
shi=BCDtoDec(ds1302_read(0x85));
ri=BCDtoDec(ds1302_read(0x87));
yue=BCDtoDec(ds1302_read(0x89));
nian=BCDtoDec(ds1302_read(0x8d));
week=BCDtoDec(ds1302_read(0x8b));
//液晶显示秒分时,日月年,星
lcd_pos(2,6);
write_display(miao);
lcd_pos(2,3);
write_display(fen);
lcd_pos(2,0);
write_display(shi);
lcd_pos(1,8);
write_display(ri);
lcd_pos(1,5);
write_display(yue);
lcd_pos(1,2);
write_display(nian);
lcd_pos(1,12);
write_week(week);
//显示温度
lcd_pos(2,10);
temper=read_temp();
if(temper<0)
{
lcd_pos(2,9);
lcd_write_date('-');
temper=0-temper;
}
else
{
lcd_pos(2,9);
lcd_write_date('');
}
lcd_pos(2,10);lcd_write_date(temper/100+0x30);
lcd_pos(2,11);lcd_write_date(temper%100/10+0x30);
lcd_pos(2,13);lcd_write_date(temper%100%10+0x30);
}
}
/****主函数****/
voidmain()
{
lcd1602_init();//LCD1602初始化
lcd1602_set();//LCD固定字符的显示
ds1302_init();//DS1302的初始化
//write_set1302();//初始化ds1302的时间,不初始化就是系统的时间
while
(1)
{
keyscan();
LCD1602display();
}
}