原创 ds18b20可怕的85度

2008-11-10 20:28 10764 4 20 分类: MCU/ 嵌入式

    用DS18B20好长时间了,从来没有自已写过18B20的程序,以前都是复制别人的,今天有空自已写了个程序,居然还是花了好长时间才调通,惭愧呀,究竟还是学到一些东西,但还是有一个问题至今没有解决,就是18B20刚上电时总会出现85度,不知道怎么回事,该延时的我也都延时了,在网上也查了,很多网友也出现了这样的问题,知道EDN有很多高手,麻烦各位给看看,下面是我写的程序,我是通过串口进行调试的.


#include <reg51.h>
#include <intrins.h>
#include <math.h>
sbit ds18b20_DQ=P1^5;
bit pos_neg_temperature=0,serial_sendflag=0;
bit readds18b20=0;
unsigned long ambient_temp;
unsigned int time="0";
unsigned char idata temperature[2]={0x00,0x00};
unsigned char strbuffer[8];
unsigned char idata send_sbuf[9]={0x62,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x55};
bit ds18b20_reset();
void ds18b20_writedata(unsigned char wdata);
unsigned char ds18b20_readdata();
void delay(unsigned int k);
void read_temp();



bit ds18b20_reset()
{
 unsigned int i;
 bit flag;
 ds18b20_DQ=0;
 for(i=240*12;i>0;i--);
 ds18b20_DQ=1;
 for(i=40*12;i>0;i--);
 flag=ds18b20_DQ;
 for(i=200*12;i>0;i--);
 return(flag);
}


void ds18b20_writedata(unsigned char wdata)
{
 unsigned char j;
 unsigned int i;
 for(i=8;i>0;i--)
 {
  ds18b20_DQ=0;
  for(j=2*12;j>0;j--);
  ds18b20_DQ= wdata&0x01;
  for(j=30*12;j>0;j--);
  ds18b20_DQ=1;
  wdata>>=1;
 }
}


unsigned char ds18b20_readdata()
{
 unsigned char j, tempdata;
 unsigned int i;
 for(i=8;i>0;i--)
 {
  tempdata>>=1;
  ds18b20_DQ = 0;
  for(j=2*12;j>0;j--);
  ds18b20_DQ = 1;
  for(j=4*12;j>0;j--);
  if(ds18b20_DQ==1)
  tempdata |= 0x80;
  for(j=30*12;j>0;j--);
  ds18b20_DQ =1;
  
 }
 return(tempdata);
}


void delay(unsigned int k)
{
 unsigned int i;
 for(i=(k/2)*12;i>0;i--);
}



void read_temp()
{
 unsigned char i;
 ds18b20_reset();
 ds18b20_writedata(0xcc);
 ds18b20_writedata(0x44);
 delay(1000000);
 ds18b20_reset();
 ds18b20_writedata(0xcc);
 ds18b20_writedata(0xbe);
 delay(1000000);
 for(i=0;i<2;i++)
 {
  temperature=ds18b20_readdata();
 }
 
 ds18b20_reset();
}


 


void change()
{
 unsigned long temp;
 unsigned char temp_data;
 temp_data=temperature[1];
 temp_data &= 0xf0;
 if(temp_data==0xf0)
 {
  pos_neg_temperature=1;
  if(temperature[0]==0)
  {
   temperature[0]=~temperature[0]+1;
   temperature[1]=~temperature[1]+1;
  }
   else
   {
    
    temperature[0]=~temperature[0]+1;
    temperature[1]=~temperature[1];
   }
  
 }
 temp=temperature[1]*256+temperature[0];
 temp=(int)((temp*625)/1000);
 if(temp==850)
 {
  ambient_temp=0;
 }
 else
 ambient_temp=temp;
}



void serial() interrupt 4 using 3
{
 if(RI)
 {
  unsigned char ch,temp,i,n=0;
  ch=SBUF;
  RI=0;
  if(ch==0x61)
  {
   for(i=0;i<=7;i++)
   {
    while(RI==0);
    temp=SBUF;
    RI=0;
    strbuffer=temp;
    if((i>=1)&&(i<=5))
    {
     n +=temp;
    }
    if(i==6)
    {
     if(n==strbuffer)
     {
      serial_sendflag=1;
     }
     else
     
      serial_sendflag=0;
     
    }
   }
  }
 }
}



void time_init()
{
 ES=1;
 TMOD=0x21;
 TH1=0xf3;
 TL1=0xf3;
 PCON=0x00;
 TR1=1;
 TR0=1;
 SCON=0x50;
 IE=0x90;
 EA=1;
 ET0=1;
 
}


timer0() interrupt 1 using 1
{
 unsigned int i;
 i=0;
 TH0=(65536-8333)/256;
 TL0=(65536-8333)%256;
 if(time==5000)
 {
  time=0;
  readds18b20=1;
 }
 time++;
}


void main()
{
 unsigned int i="0";
 time_init();
 ds18b20_reset();
 for(;;)
 {      
  TMOD=0x21;
  EA=1;
  ET0=1;
  TR0=1;
  if(readds18b20==1)
  {
   ds18b20_reset();
          read_temp();
          delay(100);
          change();
          delay(100);
          readds18b20=0;
  }
  if(serial_sendflag==1)
  {
   switch(strbuffer[1])
   {
    case 0xa1:
              send_sbuf[6]=0x00;
                     send_sbuf[5]=0x00;
                     send_sbuf[2]=0xa1;
                     send_sbuf[3]=ambient_temp/256;
                     send_sbuf[4]=ambient_temp%256;
                     if(pos_neg_temperature==1)
                     {
                      send_sbuf[5]=0x01;
                      pos_neg_temperature=0;
                     }
                     send_sbuf[7]=send_sbuf[2]+send_sbuf[3]+send_sbuf[4]+send_sbuf[5]+send_sbuf[6];
                     for(i=0;i<=8;i++)
                     {
                      SBUF=send_sbuf;
                      while(TI==0);TI=0;
                     }
           break;
           case 0xa2:
                     for(i=0;i<=8;i++)
                     {
                      SBUF=send_sbuf;
                      while(TI==0);TI=0;
                     }
           break;
   }
   serial_sendflag=0;
  }
 }

  
  

PARTNER CONTENT

文章评论16条评论)

登录后参与讨论

用户1353608 2009-12-15 16:21

这是DS18B20的特性。无法改变。18B20上电后有一段稳定时间。这个时候最好不要进行温度转换等动作。一般为1S

用户184658 2009-3-9 16:15

我不清楚你用的晶振频率是多少的,但你的延时确实有点问题,如果数小的话,误差应该不大,但数大的话,误差肯定是超过的,不可能达到你所说的效果

用户184658 2009-3-9 16:10

其实只要在程序刚开没进入循环前,先读取一次温度值,然后延时超过750MS就可以屏蔽掉了 追根究底,还是0X44指令后没延时750MS以上的话,第一次读取的温度是18B20默认的85度 如果不信的话,你把0X44温度转换之后延时750MS以上试一下,保证不会出现这种情况,只不过每次读取温度的间隔就大了

用户165568 2009-3-4 20:50

同一批片子可能大部分延时1ms就能读出正确的温度,有的需要延时10倍以上的时间才行,不过按PDF里延时750ms确实有点长

用户165568 2009-3-4 20:48

DS18B20寄存器默认上电是85度,没收到正确的指令是不会更新的

用户1376028 2009-1-15 22:42

另外: void delay(unsigned int k) { unsigned int i; for(i=(k/2)*12;i>0;i--); } 你的本意大概是: 每循环一次 消耗两个指令周期 也就是2*12us 不过现实是这个程序的运行时间是不定的

用户1376028 2009-1-15 22:39

delay(1000000); int 的表示范围是 0~65535 显然1000000超出了int的表示范围 所以delay(1000000)的真是结果是(16975) 从而造成延时不够 出现错误的85° 建议修改一下delay的内容 然后使delay(k)中k的范围在0~65535 这样子应该会没问题

用户114680 2008-11-17 11:28

85度,我认为这是延时不够,以前我也有这种情况,加了大延时,就行了

用户114680 2008-11-17 11:26

我认为这是延时不够,以前我也有这种情况,加了大延时,就行了

用户61458 2008-11-13 23:18

85度,如果18b20没有响应的话,比如没有接。那就是85度。还有,如果第一次是85的话,大部分的原因是因为延时不对。因为spec里面的采样后的延时是800ms左右。你大概在刚发出指令后就读取了。结果还没出来那。你第二次读的是你第一次发出指令后的结果,这个时候一般时间都到了,因此正确。
相关推荐阅读
用户1517802 2008-12-05 15:57
msp430
小弟我在学MSP430,感觉难度很大,很想看一下别人做的完整程序包括图,不知哪位大哥有这样的资料,不甚感激!...
用户1517802 2008-11-12 12:21
初学protel99
回到郑州了,感觉很好,上传点东西,关于PROTEL99SE的,跟大家分享,很适合初学者,让EDN的高手们见笑了, 如果觉得有用还想要其它部份,给我发邮件,xusi_mail@163.com...
用户1517802 2008-11-11 08:25
沧州行
   已经是第二次来沧州了,都是因为公司的事,这一次又在这快呆了一个多星期了,沧州是一个著名的武术之乡,但城市的发展让我丝毫看不到这个城市跟其它小城市有什么区别,去过不少中国这样的小城市,给我的总体感...
EE直播间
更多
我要评论
16
4
关闭 站长推荐上一条 /3 下一条