标题:
基于89C52 DS1302 DHT11 LCD1602温湿度时钟源码
[打印本页]
作者:
kynls0122
时间:
2018-3-17 11:41
标题:
基于89C52 DS1302 DHT11 LCD1602温湿度时钟源码
功能
1、设置闹钟2、校时
3、温湿度显示
4、实时时间
PO口为LCD1602数据接口;
有6个键
1、设置
2、移位
3、闹钟取消
4、切屏
5、加
6、减
单片机源程序如下:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char code read_addr[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
unsigned char code write_addr[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
unsigned char time[7] = {0x00,0x00, 0x12, 0x01, 0x01, 0x02, 0x18};//设置时间
unsigned char code digit[10]={"0123456789"};
uint nianshi,niange,yueshi,yuege,rvshi,rvge,shishi,shige,fenshi,fenge,miaoshi,miaoge,tempshi,tempge,humshi,humge;
uint miao,fen,shi,rv,yue,nian,timenian,timeyue,timerv,timeshi,timefen,timemiao;
uint afen=0,ashi=0,t=0,TT=0,afenshi,afenge,ashishi,ashige;
sbit SCLK=P2^1;
sbit RST=P2^0;
sbit DSIO=P2^2;
sbit LCDE=P2^6;
sbit RS=P2^7;
sbit RW=P2^5;
sbit KEY1=P1^4;//加
sbit KEY2=P1^5;//减
sbit KEY0=P1^3;//移位
sbit KEY3=P1^0;//闹铃设置
sbit KEY4=P1^2;//闹铃取消
sbit KEY5=P1^1;//切屏显示
sbit clock_beef=P3^4;//蜂鸣器输出
sbit DHTIO= P3^5 ;
uchar n,flag,num;
unsigned char U8FLAG=0,U8temp=0;
unsigned char U8T_data_H=0,U8T_data_L=0,U8RH_data_H=0,U8RH_data_L=0,U8checkdata=0;
unsigned char str[5];
//humidity 湿度
//temperature 温度
//integer 整数
//decimal 小数
unsigned char humidity_interger=0,humidity_decimal;
unsigned char temperature_integer=0,temperature_decimal;
unsigned char check;
void delay20ms()
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=222;b>0;b--)
for(a=40;a>0;a--);
}
void delay40us()
{
unsigned char a,b;
for(b=3;b>0;b--)
for(a=4;a>0;a--);
}
void dht_start() //等待接受初始化
{
DHTIO=1; //初始高电平
delay40us();
DHTIO=0; //主机拉低电平
delay20ms(); //保持电平时间大于18ms
DHTIO=1; //主机拉高电平
delay40us(); //延迟等待20-40us等待从机响应
}
unsigned char recieve_data() //数据接收
{
unsigned char i,flag,data_byte;
for(i=0;i<8;i++)
{
flag=2;
while((!DHTIO)&&flag++);//等待从机发出50us低电平结束
delay40us(); //延时超过26us-28us不超过70us
data_byte=data_byte<<1;
if(DHTIO) //如果此时dhtio为1则表示此时从机输出数据为1否则说明此时从机输出数据为0
{
data_byte|=0x01;
flag=2;
while((DHTIO)&&flag++);//等待剩下的高电平结束
}
if(!flag)
break;
}
return data_byte;
}
void dht_take_sample() //采样
{
unsigned char flag;
dht_start();
if(!DHTIO) //从机发出响应信号
{
flag=2;
while((!DHTIO)&&flag++);//检测从机发出80us低电平是否结束
flag=2;
while((DHTIO)&&flag++); //检测从机发出80us高电平是否结束
//开始采集数据
humidity_interger=recieve_data(); //采集湿度整数部分
humidity_decimal=recieve_data(); //采集湿度小数部分
temperature_integer=recieve_data(); //采集温度整数部分
temperature_decimal=recieve_data(); //采集温度小数部分
check=recieve_data(); //采集校验位
DHTIO=1; //采集数据后主机拉高电平
}
}
void delay(unsigned int z) //延时长
{
unsigned char x,y;
for(x=z;x>0;x--)
{
for(y=20;y>0;y--);
}
}
void write_com(unsigned char com) //将模式设置指令或显示地址写入液晶模块
{
RS=0;
RW=0;
LCDE=0;
P0=com;
delay(5);
LCDE=1;
delay(5);
LCDE=0;
}
void write_date(unsigned char date)//将数据(字符ASCII码)写入液晶模块
{
RS=1;
RW=0;
LCDE=0;
P0=date;
delay(5);
LCDE=1;
delay(5);
LCDE=0;
}
void L1602_string(unsigned char hang,unsigned char lie,unsigned char p) //将数据写入液晶模块
{
unsigned char a;
if(hang == 1) a = 0x80; //显示在第一行
if(hang == 2) a = 0xc0; //显示在第一行
a = a + lie -1;
write_com(a);
write_date(p);
}
void init() //1602初始化
{
write_com(0x38);
write_com(0x0e);
write_com(0x06);
write_com(0x01);
// write_com(0x80);
}
void write(unsigned char addr,unsigned char date) //ds1302根据命令字写入数据
{
unsigned char i;
RST=0;
SCLK=0;
RST=1;
delay(5);
for(i=0;i<8;i++)
{
DSIO=addr&0x01;
addr=addr>>1;
SCLK=1;
delay(5);
SCLK=0;
delay(5);
}
for(i=0;i<8;i++)
{
DSIO=date&0x01;
date>>=1;
SCLK=1;
delay(5);
SCLK=0;
delay(5);
}
RST=0;
}
unsigned char read(unsigned char addr) //ds1302读数据
{
unsigned char i,dat,dat1;
RST=0;
SCLK=0;
RST=1;
for(i=0;i<8;i++)
{
DSIO=addr&0x01;
addr>>=1;
SCLK=1;
delay(5);
SCLK=0;
delay(5);
}
delay(5);
for(i=0;i<8;i++)
{
dat1=DSIO;
dat=(dat>>1)|(dat1<<7);
SCLK=1;
delay(5);
SCLK=0;
delay(5);
}
SCLK=1;
RST=0;
return dat;
}
void readtime() // ds1302连续读出时间
{
unsigned char i;
for(i=0;i<7;i++)
{
time[i]= read(read_addr[i]);
}
}
void zhuanhuan() //十六进制转十进制
{
nianshi=time[6]/16;
niange=(time[6]&0x0f);
yueshi=time[4]/16;
yuege=(time[4]&0x0f);
rvshi=time[3]/16;
rvge=(time[3]&0x0f);
shishi=time[2]/16;
shige=(time[2]&0x0f);
fenshi=time[1]/16;
fenge=(time[1]&0x0f);
miaoshi=time[0]/16;
miaoge=(time[0]&0x0f);
}
void zhuanhuan1() //十进制转十六进制
{
time[6]=nianshi*16+niange;
time[4]=yueshi*16+yuege;
time[3]=rvshi*16+rvge;
time[2]=shishi*16+shige;
time[1]=fenshi*16+fenge;
time[0]=miaoshi*16+miaoge;
}
void xianshi() //1602显示时间
{
L1602_string(1,8,digit[nianshi]);
L1602_string(1,9,digit[niange]);
L1602_string(1,11,digit[yueshi]);
L1602_string(1,12,digit[yuege]);
L1602_string(1,14,digit[rvshi]);
L1602_string(1,15,digit[rvge]);
L1602_string(2,6,digit[shishi]);
L1602_string(2,7,digit[shige]);
L1602_string(2,9,digit[fenshi]);
L1602_string(2,10,digit[fenge]);
L1602_string(2,12,digit[miaoshi]);
L1602_string(2,13,digit[miaoge]);
}
void xianshi1() //闹铃设置显示
{
L1602_string(2,6,digit[ashishi]);
L1602_string(2,7,digit[ashige]);
L1602_string(2,9,digit[afenshi]);
L1602_string(2,10,digit[afenge]);
}
void xianshi2() //温湿度显示
{
L1602_string(1,1,'T');
L1602_string(1,2,'e');
L1602_string(1,3,'m');
L1602_string(1,4,'p');
L1602_string(1,5,':');
L1602_string(1,6,digit[tempshi]);
L1602_string(1,7,digit[tempge]);
L1602_string(1,8,'C');
L1602_string(1,9,' ');
L1602_string(1,10,' ');
L1602_string(1,11,' ');
L1602_string(1,12,' ');
L1602_string(1,13,' ');
L1602_string(1,14,' ');
L1602_string(1,15,' ');
L1602_string(2,1,'H');
L1602_string(2,2,'u');
L1602_string(2,3,'m');
L1602_string(2,4,':');
L1602_string(2,5,digit[humshi]);
L1602_string(2,6,digit[humge]);
L1602_string(2,7,'%');
L1602_string(2,8,' ');
L1602_string(2,9,' ');
L1602_string(2,10,' ');
L1602_string(2,11,' ');
L1602_string(2,12,' ');
L1602_string(2,13,' ');
L1602_string(2,14,' ');
L1602_string(2,15,' ');
}
void ds1302init() //ds1302初始化
{
unsigned char i;
write(0x8e,0x00);
for(i=0;i<7;i++)
{
write(write_addr[i],time[i]);
}
write(0x8e,0x80);
}
void tiaozhuan() //按键跳转函数
{
if(KEY0==0)
{
delay(5);
if(KEY0==0)
{
n++;
while(!KEY0);
}
}
}
void chuandi1() //时间传递函数1
{
miao=miaoshi*10+miaoge;
fen=fenshi*10+fenge;
shi=shishi*10+shige;
rv=rvshi*10+rvge;
yue=yueshi*10+yuege;
nian=nianshi*10+niange;
}
void chuandi2() //时间传递函数2
{
nianshi=nian/10;
niange=nian%10;
yueshi=yue/10;
yuege=yue%10;
rvshi=rv/10;
rvge=rv%10;
shishi=shi/10;
shige=shi%10;
fenshi=fen/10;
fenge=fen%10;
miaoshi=miao/10;
miaoge=miao%10;
}
void keyscan() //移位修改时间
{
L1602_string(1,1,'d'); //在LCD相应位置显示变量或者常量
L1602_string(1,2,'a');
L1602_string(1,3,'t');
L1602_string(1,4,'e');
L1602_string(1,5,':');
L1602_string(1,6,'2');
L1602_string(1,7,'0');
L1602_string(1,10,'.');
L1602_string(1,13,'.');
L1602_string(2,1,'t');
L1602_string(2,2,'i');
L1602_string(2,3,'m');
L1602_string(2,4,'e');
L1602_string(2,5,':');
L1602_string(2,8,':');
L1602_string(2,11,':');
if(KEY0==0)
{
delay(5);
if(KEY0==0)
{
n++;
while(!KEY0);
if(n==1);
chuandi1();
while(n==1)
{
flag=1;
write_com(0xcc); //光标回到秒十位
write_com(0x0f); //光标闪烁
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
miao++;
if(miao==60)
miao=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
miao--;
if(miao==-1)
miao=59;
chuandi2();
xianshi();
}
}
}
while(n==2)
{
write_com(0xc8);//光标回到分十位
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
fen++;
if(fen==60)
fen=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
fen--;
if(fen==-1)
fen=59;
chuandi2();
xianshi();
}
}
}
while(n==3)
{
write_com(0xc5);//光标回到时十位
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
shi++;
if(shi==24)
shi=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
shi--;
if(shi==-1)
shi=23;
chuandi2();
xianshi();
}
}
}
while(n==4)
{
write_com(0x8d) ;//光标回到日十位
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
rv++;
if(rv==32)
rv=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
rv--;
if(rv==0)
rv=31;
chuandi2();
xianshi();
}
}
}
while(n==5)
{
write_com(0x8a);//光标回到月十位
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
yue++;
if(yue==13)
yue=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
yue--;
if(yue==0)
yue=12;
chuandi2();
xianshi();
}
}
}
while(n==6)
{
write_com(0x87);//光标回到年十位
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
nian++;
if(nian==101)
nian=0;
chuandi2();
xianshi();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
nian--;
if(nian==-1)
nian=100;
chuandi2();
xianshi();
}
}
if(KEY0==0)
{
delay(5);
if(KEY0==0)
{
n=0;
flag=0;
write_com(0x0c);
while(!KEY0);
}
}
}
zhuanhuan1();
ds1302init();
}
}
}
void alarm_set()//闹铃设置
{
if(KEY3==0)
{
t=1;
delay(5);
if(KEY3==0)
{
while(!KEY3);
L1602_string(1,1,'a'); //在LCD相应位置显示变量或者常量
L1602_string(1,2,'l');
L1602_string(1,3,'a');
L1602_string(1,4,'r');
L1602_string(1,5,'m');
L1602_string(1,6,' ');
L1602_string(1,7,'s');
L1602_string(1,8,'e');
L1602_string(1,9,'t');
L1602_string(1,10,':');
L1602_string(1,11,' ');
L1602_string(1,12,' ');
L1602_string(1,13,' ');
L1602_string(1,14,' ');
L1602_string(1,15,' ');
L1602_string(2,1,' ');
L1602_string(2,2,' ');
L1602_string(2,3,' ');
L1602_string(2,4,' ');
L1602_string(2,5,' ');
afenshi=afen/10;
afenge=afen%10;
ashishi=ashi/10;
ashige=ashi%10;
xianshi1();
while(KEY3)
{
if(KEY0==0)
{
delay(5);
if(KEY0==0)
{
n++;
while(!KEY0);
while(n==1)
{
write_com(0xc8);//光标回到分十位
write_com(0x0f);
tiaozhuan();
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
afen++;
if(afen==60)
afen=0;
afenshi=afen/10;
afenge=afen%10;
xianshi1();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
afen--;
if(afen==-1)
afen=59;
afenshi=afen/10;
afenge=afen%10;
xianshi1();
}
}
}
while(n==2)
{
write_com(0xc5); //光标回到时十位
if(KEY1==0)
{
delay(5);
if(KEY1==0)
{
while(!KEY1);
ashi++;
if(ashi==24)
ashi=0;
ashishi=ashi/10;
ashige=ashi%10;
xianshi1();
}
}
if(KEY2==0)
{
delay(5);
if(KEY2==0)
{
while(!KEY2);
ashi--;
if(ashi==-1)
ashi=23;
ashishi=ashi/10;
ashige=ashi%10;
xianshi1();
}
}
if(KEY0==0)
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
2018-01-10 134828.zip
(4.15 KB, 下载次数: 109)
2018-3-17 11:38 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
51单片机小白龙
时间:
2020-5-8 20:55
走时慢了很多,而且断电后不保存ds1302,又重新计数了
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1