基于AT89C51的DS18B20温度传感器读写程序
#include <intrins.h>
sbit DQ=P1^0; //温度传感器数据线接口
//DS18B20初始化
bit DS18B20Init(void)
{
unsigned int i,j;
DQ=1; //(1) 先将数据线置高电平“1”。
_nop_(); //(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
DQ=0; //(3) 数据线拉到低电平“0”。
for(i=0;i<750;i++)
_nop_(); //(4) 延时750微秒(该时间的时间范围可以从480到960微秒)
DQ=1; //(5) 数据线拉到高电平“1”。
for(i=0;i<540;i++) //(6) 延时等待(如果初始化成功则在15到60微秒时间之内产生一个由DS18B20所返回的低电平“0”。
{
_nop_();
if(DQ==0) {P3=0x00;break;}
else continue;
}
if(i>=60)
return 1; //初始化失败
for(j=i;j<540-i;j++) _nop_(); //(7) 若CPU读到了数据线上的低电平“0”后,还要做延时,
//其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
DQ=1; //(8) 将数据线再次拉高到高电平“1”后结束。
_nop_();
return 0; //初始化成功
}
//发送一个字节的数据
void WriteDat(unsigned char dat)
{
unsigned char i,j;
ACC=dat;
for(i=0;i<8;i++)
{
DQ=1;
switch(ACC&0x01)
{
case 0: //写0
{
DQ=0;
for(j=0;j<30;j++) _nop_();
break;
}
case 1: //写1
{
DQ=0;
_nop_();
DQ=1;
for(j=0;j<30;j++); _nop_();
break;
}
}
for(j=0;j<15;j++) _nop_();
ACC=ACC>>1; //下一位
}
DQ=1;
_nop_();
}
//读一个字节的数据
unsigned char ReadDat(void)
{
unsigned char temp=0x00;
unsigned char i,j;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
for(j=0;j<15;j++)
_nop_();
DQ=1;
_nop_();
F0=DQ;
if(F0) ACC=0x80;
else ACC=0x00;
temp=ACC|0xff;
temp=temp>>1;
for(j=0;j<30;j++)
_nop_();
}
return temp;
}
//Temperature计算,把从RAM中读出的数计算成一个完整的可以用于表示当前温度的值
////如果温度是0度下则最高位为1,否则为0
float TempCal(unsigned char TPH,unsigned char TPL)
{
unsigned char TempDat[2];//第一位是整数部分,第二位是小数部分
float Temp;
TempDat[0]=(((TPL&0xf0)>>4)|((TPH&0x0f)<<4)); //取整数
TempDat[1]=TPL&0x0f; //取小数
if(TPH&0xf8)
{
TempDat[0]=~TempDat[0];
TempDat[1]=(TempDat[1]^0x0f)+0x01;
Temp=((float)(TempDat[0]|0x80)+(float)TempDat[1]*0.0625);
}
else
Temp=(float)TempDat[0]+(float)TempDat[1]*0.0625;
return Temp;
}
float StartTemp(void)
{
unsigned char RamDat[9];
unsigned int i;
if(DS18B20Init()); //器件复位,如果为1则复位不成功,0则复位成功
return 255;
WriteDat(0xcc); //跳过器件匹配
WriteDat(0x44); //启动温度转换
for(i=0;i<900;i++)
_nop_();
WriteDat(0xbe);
for(i=0;i<9;i++) //读RAMD数据
RamDat[i]=ReadDat();
return TempCal(RamDat[1],RamDat[0]);
}
凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!
