温度传感器DS18B20ATC89S51单片机LCD1602液晶显示测温+可调时钟系统C程序完整版.docx
《温度传感器DS18B20ATC89S51单片机LCD1602液晶显示测温+可调时钟系统C程序完整版.docx》由会员分享,可在线阅读,更多相关《温度传感器DS18B20ATC89S51单片机LCD1602液晶显示测温+可调时钟系统C程序完整版.docx(22页珍藏版)》请在冰豆网上搜索。
温度传感器DS18B20ATC89S51单片机LCD1602液晶显示测温+可调时钟系统C程序完整版
基于ds18b20STC89s51单片机测温系统LCD1602液晶
可调时钟+温度显示
(C程序完整版)
温度传感器的种类众多,在应用与高精度、高可靠性的场合时DALLAS(达拉斯)公司生产的DS18B20温度传感器当仁不让。
超小的体积,超低的硬件开消,抗干扰能力强,精度高,附加功能强,使得DS18B20更受欢迎。
对于我们普通的电子爱好者来说,DS18B20的优势更是我们学习单片机技术和开发温度相关的小产品的不二选择。
了解其工作原理和应用可以拓宽您对单片机开发的思路。
如果要更全的资料请搜索“完整的ds18b20中文资料.pdf “。
DS18B20的主要特征:
„ 全数字温度转换及输出。
„ 先进的单总线数据通信。
„ 最高12位分辨率,精度可达土0.5摄氏度。
„ 12位分辨率时的最大工作周期为750毫秒。
„ 可选择寄生工作方式。
„ 检测温度范围为–55°C~+125°C(–67°F~+257°F)
„ 内置EEPROM,限温报警功能。
„ 64位光刻ROM,内置产品序列号,方便多机挂接。
„ 多样封装形式,适应不同硬件系统。
DS18B20引脚功能:
·GND电压地 ·DQ 单数据总线 ·VDD 电源电压 ·NC 空引脚
DS18B20工作原理及应用:
DS18B20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。
其一个工作周期可分为两个部分,即温度检测和数据处理。
在讲解其工作流程之前我们有必要了解18B20的内部存储器资源。
18B20共有2种形态的存储器资源,它们分别是:
1> ROM 只读存储器,用于存放DS18B20ID编码,其前8位是单线系列编码(DS18B20的编码是19H),后面48位是芯片唯一的序列号,最后8位是以上56的位的CRC码(冗余校验)。
数据在出产时设置不由用户更改。
DS18B20共64位ROM。
2> RAM 数据暂存器,用于内部计算和数据存取,数据在掉电后丢失,DS18B20共9个字节RAM,每个字节为8位。
第1、2个字节是温度转换后的数据值信息,第3、4个字节是用户EEPROM(常用于温度报警值储存)的镜像。
在上电复位时其值将被刷新。
第5个字节则是用户第3个EEPROM的镜像。
第6、7、8个字节为计数寄存器,是为了让用户得到更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单元。
第9个字节为前8个字节的CRC码。
EEPROM 非易失性记忆体,用于存放长期需要保存的数据,上下限温度报警值和校验数据,DS18B20共3位EEPROM,并在RAM都存在镜像,以方便用户操作。
C程序(独家专售):
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLCDIOP2
sbitDQ=P3^7;//ds18b20与单片机连接口
sbitrs=P3^0;
sbitrd=P3^1;
sbitlcden=P3^2;
sbits1=P1^3;
sbits2=P1^4;
sbits3=P1^5;
uchardatadisdata[5];
uinttvalue;//温度值
uchartflag;
ucharcount,s1num;
charmiao,shi,fen,day=18,mon=11,week=0;
uintyear=2010;
ucharcodetable[]="2010-11-18THU";
ucharcodetable1[]="00:
00:
00000.0C";
ucharcodetable2[]="THUFRISATSUNMONTUEWES";
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voidwrite_com(ucharcom)
{
rs=0;
rd=0;
lcden=0;
P2=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
voidwrite_date(uchardate)
{
rs=1;
rd=0;
lcden=0;
P2=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
voidinit()
{
ucharnum;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_date(table1[num]);
delay(5);
}
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
voidwrite_sfm(ucharadd,uchardate)
{
ucharshi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
voidwrite_md(ucharadd,uchardate)
{
ucharshi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
voidwrite_year(ucharadd,uintdate)
{
ucharqian,bai,shi,ge;
qian=date/1000;
bai=date%1000/100;
shi=date%1000%100/10;
ge=date%1000%100%10;
write_com(0x80+add);
write_date(0x30+qian);
write_date(0x30+bai);
write_date(0x30+shi);
write_date(0x30+ge);
}
voidwrite_week(ucharadd,uchardate)
{
ucharnum;
write_com(0x80+add);
for(num=0;num<3;num++)
{
write_date(table2[date]);
date++;
delay(5);
}
}
voiddisplay()
{
mon++;
if(mon==13)
{
mon=1;
year++;
write_year(1,year);
}
write_md(6,mon);
}
voidkeyscan()
{
rd=0;
if(s1==0)
{
delay(5);
if(s1==0)
{
s1num++;//全局变量
while(!
s1);
if(s1num==1)//调时间时//
{
TR0=0;//定时器停止//
write_com(0x80+4);
write_com(0x0f);//光标闪射//
}
if(s1num==2)//调时间时//
{
write_com(0x80+7);
}
if(s1num==3)//调时间时//
{
write_com(0x80+10);
}
if(s1num==4)//调时间时//
{
write_com(0x80+14);
}
if(s1num==5)//调时间时//
{
write_com(0x80+0x40+1);
}
if(s1num==6)//调时间分//
{
write_com(0x80+0x40+4);
}
if(s1num==7)//调时间秒
{
write_com(0x80+0x40+7);//光标位置//
}
if(s1num==8)
{
s1num=0;//s1num清零//
write_com(0x0c);//光标不闪烁//
TR0=1;//定时器又开始//
}
}
}
if(s1num!
=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!
s2);
if(s1num==7)
{
miao++;
if(miao==60)
miao=0;
write_sfm(6,miao);
write_com(0x80+0x40+7);
}
if(s1num==6)
{
fen++;
if(fen==60)
fen=0;
write_sfm(3,fen);
write_com(0x80+0x40+4);
}
if(s1num==5)
{
shi++;
if(shi==24)
shi=0;
write_sfm(0,shi);
write_com(0x80+0x40+1);
}
if(s1num==3)
{
week=week+3;
if(week==21)
week=0;
day++;
if(((mon==1)||(mon==3)||(mon==5)||(mon==7)||(mon==8)||(mon==10)||(mon==12))&&(day==32))
{day=1;
}
if(((mon==4)||(mon==6)||(mon==9)||(mon==11))&&(day==31))
{day=1;
}
if(((mon==2)&&(((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==30))
{day=1;
}
if(((mon==2)&&(!
((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==29))
{day=1;
}
write_md(9,day);
write_week(12,week);
write_com(0x80+10);
}
if(s1num==2)
{
mon++;
if(mon==13)
mon=1;
write_md(6,mon);
write_com(0x80+7);
}
if(s1num==1)
{
year++;
write_year(1,year);
write_com(0x80+4);
}
if(s1num==4)
{
week+=3;
if(week==21)
week=0;
write_week(12,week);
write_com(0x80+14);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!
s3);
if(s1num==7)
{
miao--;
if(miao==-1)
miao=59;
write_sfm(6,miao);
write_com(0x80+0x40+7);
}
if(s1num==6)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(3,fen);
write_com(0x80+0x40+4);
}
if(s1num==5)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(0,shi);
write_com(0x80+0x40+1);
}
if(s1num==3)
{
week=week-3;
if(week==-3)
week=0;
day--;
if(((mon==1)||(mon==3)||(mon==5)||(mon==7)||(mon==8)||(mon==10)||(mon==12))&&(day==0))
{day=31;
}
if(((mon==4)||(mon==6)||(mon==9)||(mon==11))&&(day==0))
{day=30;
}
if(((mon==2)&&(((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==0))
{day=29;
}
if(((mon==2)&&(!
((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==0))
{day=28;
}
write_md(9,day);
write_week(12,week);
write_com(0x80+10);
}
if(s1num==2)
{
mon--;
if(mon==0)
mon=12;
write_md(6,mon);
write_com(0x80+7);
}
if(s1num==1)
{
year--;
write_year(1,year);
write_com(0x80+4);
}
if(s1num==4)
{
week-=3;
if(week==-3)
week=18;
write_week(12,week);
write_com(0x80+14);
}
}
}
}
}
voiddelay_18B20(unsignedinti)//延时1微秒
{
while(i--);
}
voidds1820rst()/*ds1820复位*/
{unsignedcharx=0;
DQ=1;//DQ复位
delay_18B20(4);//延时
DQ=0;//DQ拉低
delay_18B20(100);//精确延时大于480us
DQ=1;//拉高
delay_18B20(40);
}
uchards1820rd()/*读数据*/
{unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
voidds1820wr(ucharwdata)/*写数据*/
{unsignedchari=0;
for(i=8;i>0;i--)
{DQ=0;
DQ=wdata&0x01;
delay_18B20(10);
DQ=1;
wdata>>=1;
}
}
read_temp()/*读取温度值并转换*/
{uchara,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else
{tvalue=~tvalue+1;
tflag=1;
}
tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
return(tvalue);
}
voidds1820disp()//温度值显示
{ucharflagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位
if(tflag==0)
flagdat=0x20;//正温度不显示符号
else
flagdat=0x2d;//负温度显示负号:
-
if(disdata[0]==0x30)
{disdata[0]=0x20;//如果百位为0,不显示
if(disdata[1]==0x30)
{disdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
write_com(0xc8);
write_date(flagdat);//显示符号位
write_com(0xc9);
write_date(disdata[0]);//显示百位
write_com(0xca);
write_date(disdata[1]);//显示十位
write_com(0xcb);
write_date(disdata[2]);//显示个位
write_com(0xcc);
write_date(0x2e);//显示小数点
write_com(0xcd);
write_date(disdata[3]);//显示小数位
write_com(0xcf);
write_date('C');
}
voidmain()
{
init();
delay(5);
read_temp();//读取温度
ds1820disp();//显示
while
(1)
{
keyscan();
delay(5);
}
}
voidtimer0()interrupt1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==18)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
day++;
week=week+3;
if(week==21)
week=0;
if(((mon==1)||(mon==3)||(mon==5)||(mon==7)||(mon==8)||(mon==10)||(mon==12))&&(day==32))
{day=1;
display();
}
if(((mon==4)||(mon==6)||(mon==9)||(mon==11))&&(day==31))
{day=1;
display();
}
if(((mon==2)&&(((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==30))
{day=1;
display();
}
if(((mon==2)&&(!
((year%4==0)&&(year%100!
=0))||(year%400==0)))&&(day==29))
{day=1;
display();
}