打印

请问怎么解决18B20测温时总显示85的问题

[复制链接]
13530|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaofei207|  楼主 | 2009-12-21 22:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近写了一个用at89s52和18b20的测温程序,但为何在数码管上的显示一直是8.5呢?
网上有许多解释,有的说温度读取后需要一定的转换时间,出现85的问题很大可能是转换时间不够 ;85是电源供电的问题,如果是寄生供电要保证1S以上的充电时间,转换开始后要尽快转到高电平,并保持1S以上,可以把上拉电阻减小到1K5试试 ;
有的说是忘了跳过ROM匹配,因此造成温度转换不成功,读到的是18B20暂存器中的温度上电缺省值85度,还有的说是电源端接触不良,偶尔出85度,焊好后,就正常了 ……
   
但我还是不太明白,小弟是一名初学者,请大家帮忙分析哈,不能感激!
附代码如下:
//18B20单线温度检测的应用样例程序
#include<REG52.H>
#include<math.h>
#include<INTRINS.H>
#define uchar unsigned char
#define uint   unsigned int
uchar temp;
uchar code tab[]={0x39,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ;
sbit DQ=P1^7;//ds18b20 端口
void delay15us(uchar n )
{
do
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();
n--;
}while(n);
}
//18b20初始化函数
unsigned Init_DS18B20(void)
{
uint answer_flag;
DQ = 0;   
delay15us(35);  //延时480~960us
DQ = 1;     
delay15us(2); //延时15~60us等待响应
answer_flag=DQ;  //采样应答脉冲信号
//delay15us(6);//延时60~240us
//delay15us(25);
return(answer_flag);
}
//读取一位
uchar Readbit(void)
{
bit s;
DQ=1; //拉高数据线,延时1s,准备启动读时隙
_nop_();
DQ=0;  //保持低电平1us,但不能高于15us
_nop_(); _nop_();
_nop_(); _nop_();
_nop_(); _nop_();
DQ=1;    //在15us之内,停止低电平
s=DQ;    //读取一位数据
delay15us(4);//读时序不低于60us
return(s);
}
uchar Readbyte(void)  //读取数据的一个字节
{
uchar i,j,by;
by=0;
for(i=0;i<8;i++)
{
  j=Readbit();
  by=(j<<7)|(by>>1);
}
return(by);
}
//写一个字节
void WriteOneChar(unsigned char byte)
{
unsigned int i=0;
bit n;
for (i=8; i>0; i--)
   {
   DQ = 1;
    _nop_();
   n=byte&0x01;
   byte=byte>>1;
   if(n)    //写1
    {
   DQ=0;
  _nop_(); _nop_();
     _nop_(); _nop_();
  _nop_(); _nop_();
  _nop_(); _nop_();
  DQ=1;
  delay15us(4);
    }
   else
  {
  DQ=0;
  delay15us(6);
  DQ=1;
  _nop_(); _nop_();
  _nop_(); _nop_();
  }
}
}
void convert(void)//启动温度转换
{
Init_DS18B20();//初始化,复位
if(Init_DS18B20()) //接受到应答脉冲
{
  delay15us(7);   //延时1ms
  WriteOneChar(0xcc);//skip rom
     WriteOneChar(0x44);//convert T
}
}
//读取温度
uchar ReadTemperature(void)
{
uchar a,b,t;
convert();
  delay15us(7000);//1s
Init_DS18B20();
if( Init_DS18B20())
{
  delay15us(7); //1ms
  WriteOneChar(0xcc);
  WriteOneChar(0xbe);
  a=Readbyte();  //读取温度低位字节
  b=Readbyte();  //高位
  b<<=4;
   b+=(a&0xf0)>>4;
  t=b;
  return(t);

  }
}
void dispaly()
{
P2=0;
P0=tab[temp/10];
delay15us(200);
P2=1;
P0=tab[temp%10];
delay15us(200);
P2=2;
P0=tab[0];
delay15us(200);
}
void main()
{

while(1)
{
  dispaly();
  temp=ReadTemperature();
  
}
}


书上说如果测的温度>0,将结果乘以0.0625,<0,将测得的温度取反加1再乘0.0625,这个怎么处理呢?

相关帖子

沙发
znmcu| | 2009-12-22 00:15 | 只看该作者
DS18b20.c

#include "DS18b20.h"
#include "myfun.h"

/*******************************************************

        +-------------------------------------+
        |  振南电子 驱动程序模块 DS18B20 部分 |
        +-------------------------------------+

  此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
        严禁随意用于商业目的,违者必究,后果自负
         振南电子
             ->产品网站 http://www.znmcu.cn/
             ->产品网店 http://shop.znmcu.cn/
             ->产品咨询 QQ:987582714
                                    MSN:yzn07@126.com
                            WW:yzn07       
                                                                          
********************************************************/

/******************************************************************
- 功能描述:DS18B20初始化
- 隶属模块:DS18B20模块
- 函数属性:外部,供用户使用
- 参数说明:无      
- 返回说明:返回值为0说明初始化成功,否则失败
- 注:初始化是正确操作DS18B20是重要一步,必须初始化成功
******************************************************************/

unsigned char DS18B20_Init()
{
unsigned char x=0;
DQ=1;       //DQ复位
delay(96);  //稍做延时
DQ=0;       //单片机将DQ拉低
delay(960); //精确延时 大于 480us
DQ=1;       //拉高总线
delay(168);
x=DQ;       //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(240);
return x;
}

/******************************************************************
- 功能描述:从DS18B20读取一个字节
- 隶属模块:DS18B20模块
- 函数属性:内部
- 参数说明:无      
- 返回说明:从DS18B20读到的字节
- 注:无
******************************************************************/

unsigned char DS18B20_ReadByte()
{
unsigned char i=0,dat=0;
for(i=0;i<8;i++)
{
  DQ=0;    //给脉冲信号
  dat>>=1;
  DQ = 1;  //给脉冲信号
  if(DQ) dat|=0x80;
  delay(48);
}
return(dat);
}

/******************************************************************
- 功能描述:向DS18B20写入一个字节
- 隶属模块:DS18B20模块
- 函数属性:内部
- 参数说明:dat:将要向DS18B20写入字节      
- 返回说明:无
- 注:无
******************************************************************/

void DS18B20_WriteByte(unsigned char dat)
{
unsigned char i=0;
for(i=0;i<8;i++)
{
  DQ=0;
  DQ=dat&0x01;
  delay(60);
  DQ=1;
  dat>>=1;
}
}

/******************************************************************
- 功能描述:从DS18B20中读取温度
- 隶属模块:DS18B20模块
- 函数属性:外部,供用户使用
- 参数说明:无      
- 返回说明:由于返回的温度是浮点数(即小数),为了方便返回的值将为原
             值的100倍,即精确到小数点后2位,用户需要对返回值除以100
                         得到实际的温度值
- 注:这里读取温度是以DS18B20的最高精度来读取的,即12位
******************************************************************/

unsigned int DS18B20_ReadTemperature()
{
unsigned int t=0;
DS18B20_Init();
DS18B20_WriteByte(0xcc); // 跳过读序号列号的操作
DS18B20_WriteByte(0x44); // 启动温度转换
DS18B20_Init();
DS18B20_WriteByte(0xcc); //跳过读序号列号的操作
DS18B20_WriteByte(0xbe); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
((unsigned char *)&t)[1]=DS18B20_ReadByte();
((unsigned char *)&t)[0]=DS18B20_ReadByte();
return (t!=1360)?(t*6.25):0; //DS18B20有一个常见的问题,即所谓的85问题
                              //刚上电时可能读回的温度值是85,这是错误的值,应舍弃
}
DS18b20.h

#ifndef  _DS18B20_H_
#define  _DS18B20_H_

#include "reg51.h"

/*******************************************************

        +-------------------------------------+
        |  振南电子 驱动程序模块 DS18B20 部分 |
        +-------------------------------------+

  此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
        严禁随意用于商业目的,违者必究,后果自负
         振南电子
             ->产品网站 http://www.znmcu.cn/
             ->产品网店 http://shop.znmcu.cn/
             ->产品咨询 QQ:987582714
                                    MSN:yzn07@126.com
                            WW:yzn07       
                                                                          
********************************************************/

sbit DQ=P1^4; //DS18B20的数据端

unsigned char DS18B20_Init();
unsigned char DS18B20_ReadByte();
void DS18B20_WriteByte(unsigned char dat);
unsigned int DS18B20_ReadTemperature();

#endif

使用特权

评论回复
板凳
gaofei207|  楼主 | 2009-12-22 11:57 | 只看该作者
2# znmcu

首先感谢这位朋友的指点,但不知"myfun.h"头文件是什么?

使用特权

评论回复
地板
gaofei207|  楼主 | 2009-12-22 12:09 | 只看该作者
请各位大侠多多帮忙啊 ,小弟不胜感激!

使用特权

评论回复
5
znmcu| | 2009-12-22 12:24 | 只看该作者
myfun 是我程序模块中的常用常用函数模块

myfun.h

#ifndef  _MYFUN_H_
#define  _MYFUN_H_

/*******************************************************

        +------------------------------------+
        |振南电子 原创程序模块 公共函数部分  |
        +------------------------------------+

  此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
        严禁随意用于商业目的,违者必究,后果自负
         振南电子
             ->产品网站 http://www.znmcu.cn/
             ->产品论坛 http://bbs.znmcu.cn/
             ->产品网店 http://shop.znmcu.cn/
             ->产品咨询 QQ:987582714 MSN:yzn07@126.com
                        WW:yzn07                                  
********************************************************/

void delay(unsigned int time); //延时函数
void u32tostr(unsigned long dat,char *str);        //将一个32位的变量dat转为字符串
unsigned long strtou32(char *str); //将一个字符串转为32位的变量

#endif
myfun.c

#include "myfun.h"
#include "string.h"

/*******************************************************

        +------------------------------------+
        |振南电子 原创程序模块 公共函数部分  |
        +------------------------------------+

  此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
        严禁随意用于商业目的,违者必究,后果自负
         振南电子
             ->产品网站 http://www.znmcu.cn/
             ->产品论坛 http://bbs.znmcu.cn/
             ->产品网店 http://shop.znmcu.cn/
             ->产品咨询 QQ:987582714 MSN:yzn07@126.com
                        WW:yzn07                                  
********************************************************/

/******************************************************************
- 功能描述:延时函数
- 隶属模块:公开函数模块
- 函数属性:外部,用户可调用
- 参数说明:time:time值决定了延时的时间长短           
- 返回说明:无
- 注:.....
******************************************************************/

void delay(unsigned int time)
{
while(time--);
}

/******************************************************************
- 功能描述:将一个32位的变量dat转为字符串,比如把1234转为"1234"
- 隶属模块:公开函数模块
- 函数属性:外部,用户可调用
- 参数说明:dat:带转的long型的变量
             str:指向字符数组的指针,转换后的字节串放在其中           
- 返回说明:无
******************************************************************/

void u32tostr(unsigned long dat,char *str)
{
char temp[20];
unsigned char i=0,j=0;
i=0;
while(dat)
{
  temp[i]=dat%10+0x30;
  i++;
  dat/=10;
}
j=i;
for(i=0;i<j;i++)
{
  str[i]=temp[j-i-1];
}
if(!i) {str[i++]='0';}
str[i]=0;
}

/******************************************************************
- 功能描述:将一个字符串转为32位的变量,比如"1234"转为1234
- 隶属模块:公开函数模块
- 函数属性:外部,用户可调用
- 参数说明:str:指向待转换的字符串           
- 返回说明:转换后的数值
******************************************************************/

unsigned long strtou32(char *str)
{
unsigned long temp=0;
unsigned long fact=1;
unsigned char len=strlen(str);
unsigned char i;
for(i=len;i>0;i--)
{
  temp+=((str[i-1]-0x30)*fact);
  fact*=10;
}
return temp;
}

使用特权

评论回复
6
ningling_21| | 2009-12-22 12:32 | 只看该作者
我的是上电后头一次显示85,以后就不会了。

使用特权

评论回复
7
hab2000| | 2009-12-22 14:57 | 只看该作者
貌似楼主未启动温度转换喔!
仔细查查看!

使用特权

评论回复
8
gaofei207|  楼主 | 2009-12-22 16:31 | 只看该作者
6# ningling_21

是的,在网上查了下,据说18b20测温时第一次都会显示85,随后就能测到正确的温度了,但我的程序一直显示85,哎,不知何解?

使用特权

评论回复
9
gaofei207|  楼主 | 2009-12-22 16:37 | 只看该作者
7# hab2000

convert();这函数好像有启动温度转换的命令,
还是非常感谢7楼朋友热心的帮助……

使用特权

评论回复
10
gaofei207|  楼主 | 2009-12-22 16:45 | 只看该作者
5# znmcu

呵呵,感谢你分享格式相当规范的代码,很值得我们这些菜鸟认真学习,但我用了后却是一直显示8.9,不知何缘故?
((unsigned char *)&t)[1]=DS18B20_ReadByte();

((unsigned char *)&t)[0]=DS18B20_ReadByte();

return (t!=1360)?(t*6.25):0; //DS18B20有一个常见的问题,即所谓的85问题

                              //刚上电时可能读回的温度值是85,这是错误的值,应舍弃

这部分的温度数值处理我看得不太明白,能否耐心解释一下?谢啦~

使用特权

评论回复
11
znmcu| | 2009-12-22 17:02 | 只看该作者
我的程序是运行在51上的,1T,晶振是22.1184M,程序里的delay因为你硬件不同,延时时间也有不同,你要自己改一下
比如 你如果用普通51 12分频 晶振12M 那么你内核频率是1M,你就要把我程序里的delay的参数/22 这样才可以的
DS18B20对时间很敏感的

使用特权

评论回复
12
feng186jie| | 2009-12-22 17:03 | 只看该作者
/*温度采集程序
1、传感器DS18B20
2、输出:tempeature温度值、t_sign[]状态
*/
//---------------------------------------------
#define uchar unsigned         char
#define uint  unsigned         int
#define sint  signed        int
#define schar signed    char
//=============================================
//工作参数
#define TEMP_WAIT                10                        //等待温度转换完成
#define TEMP_HIG                2000                //温度范围 125度 最大值 2000*0.0625=125
#define        TEMP_LOW                -880                //温度范围 -55度 最小值 -880*0.0625=-55
#define TEMP_K                        0.625                //温度系数,从传感器读出的值×TEMP_K=实际温度值
#define ERR_MAX                        5                        //传感器连续错误次数检测
//==============================================
//字符定义
#define ERR                                0                        //错误标志
#define OLD                                1                        //数据准备好标志
#define END                                2                        //数据采集结束标志
#define OVERFLOW                3                        //数据溢出标志
//传感器引脚
#define WRIT_DDR_0   DDRB &= ~(1 << DDB0)  
#define WRIT_DDR_1   DDRB |= (1 << DDB0)                   
#define WRIT_POT_0   PORTB &= ~(1 << DDB0)
#define WRIT_POT_1   PORTB |= (1 << DDB0)
//===============================================
//全局变量
uchar        temp_count,temp_wait;                //温度采集相关寄存器
sint    temp_reg;
uchar   temp_err_c;                                        //温度传感器错误读取错误寄存器       
sint    temp_buff[3];
uchar   t_sign[4];
sint    temperature;
//===============================================
//DS18B20驱动程序       
void  delay(unsigned int);                        //延时函数               
void  ds18b20_write(uchar);                        //写1个字节
uchar ds18b20_read(void);                        //读1个字节
uchar reset(void);                                        //复位
//===============================================


/************************************************
函数名称:温度变换函数
函数参数:通道号
                  局部变量temp_count (温度采集数据组数 0-3),temp_wait(温度采集进程),
                  标志位: temp_err(传感器错误),temp_overflow(温度值溢出),temp_old(温度值准备就绪)
返 回 值:temperature(当前温度值×10)       
备    注:传感器=18B20
*************************************************/
void call_temp(void)
{       
        uchar a,b;       
//执行程序
        switch(temp_wait)
        {
                 case 0:temp_wait++;
                       a=reset();
                           if(a){temp_wait=0;temp_err_c++;t_sign[END]=1;        }        //无复位信号//未完成温度采集//传感器错误       
                           break;
                case 1:temp_wait++;
                       ds18b20_write(0XCC);                                                     //忽略ROM匹配
                           ds18b20_write(0X44);                                                     //发送温度转化命令
                           break;
            case TEMP_WAIT:
                       temp_wait++;
                           a=reset();                                                              //复位等待从机应答
                       if(a){temp_wait=0;temp_err_c++;t_sign[END]=1;        }        //无复位信号//未完成温度采集//传感器错误       
                   break;
                case (TEMP_WAIT+1):
                       temp_wait++;
                           ds18b20_write(0XCC);                                                //忽略ROM匹配
                           ds18b20_write(0XBE);                                                //发送读温度命令   
               break;       
                case (TEMP_WAIT+2):
                       temp_wait++;
                           temp_reg=ds18b20_read();                                                                //读出温度低8                                       
                           DDRB &=~(1<<DDB0);                                            //释放总线
                           break;
            case (TEMP_WAIT+3):
                       temp_wait++;
                           temp_reg=temp_reg|(ds18b20_read()<<8);                             //读出温度高8位
                           DDRB &=~(1<<DDB0);
                           break;
                case (TEMP_WAIT+4):
                       temp_wait=0;                                                                                        //数据完成
                           temp_err_c=0;                                                                                //传感器数据读取正常
                           t_sign[ERR]=0;                                                                                //
                           //
                           if((TEMP_LOW<=temp_reg)&&(temp_reg<=TEMP_HIG))                //数据是否在允许范围内
                           {                                                                                                        //数据未溢出       
                                        temp_buff[temp_count]=temp_reg;                                        //将数据保存在缓存中
                                        if(temp_count>=2){temp_count=0;}                                //温度已采集3次以上               
                                        else        temp_count++;                                                        //修改指针,以更新数据。
                                        //在3组数据数值中,取出中间值。
                                        for(b=0;b<2;b++)
                                        {
                                                 for(a=0;a<2-b;a++)
                                                if(temp_buff[a]>temp_buff[a+1])
                                                {
                                                         temp_reg=temp_buff[a+1];
                                                        temp_buff[a+1]=temp_buff[a];
                                                        temp_buff[a]=temp_reg;
                                                }
                                        }
                                        //计算实际温度值
                                        temperature=(sint)(temp_buff[1]*TEMP_K);                //传感器读出的数据×系数=实际温度值。
                                        //连续采集3次以上数据后,数据准备就绪
                                        if(temp_count>1)t_sign[OLD]=1;                                //数据准备完成
                                        //温度采集正常
                                        temp_err_c=0;                                                                //传感器数据读取正常
                                           t_sign[ERR]=0;                                                                //
                                        //       
                           }
                           else        temp_wait=0;                                                                //数据溢出
                           //
                           t_sign[END]=1;                                                                    //温度采集完成
                           break;
                default:
                       {
                              if(temp_wait>(TEMP_WAIT+4))temp_wait=0;
                              else temp_wait++;
                           }       
        }
        //====================================
        //传感器错误检测
        if(temp_err_c>=ERR_MAX)
        {
            temp_err_c=ERR_MAX;
            t_sign[ERR]=1;
                temp_count=0;
                t_sign[OLD]=0;
        }//温度传感器错误
}
//======================================================

/***********************************
函数名称:DS18B20复位
函数参数:通道号
返 回 值:返回0成功,反1失败       
备    注:无
**********************************/

unsigned char reset(void)
{
        unsigned char presence=1;
    WRIT_DDR_1;
        WRIT_POT_0;
                                                                   //主机拉至低电平
    delay(250);  
        WRIT_POT_1;
        WRIT_DDR_0;                                                //延时503us
                                                                   //释放总线等电阻拉高总线,并保持15~60us
        delay(35);                                           //延时70us
    presence=PINB;                                           //没有接收到应答信号,继续复位
    presence=presence&0x01;                         //接收到应答信号
        delay(200);                                                                  //延时
        return(presence);
}
//============================================
       
/***********************************
函数名称:DS18B20  读1个字节
函数参数:通道号
返 回 值:读出值       
备    注:无
**********************************/

unsigned char ds18b20_read(void)
{
          unsigned char i,byte,temp;
        byte=0x00;
        for(i=0;i<8;i++)
        {
                 WRIT_DDR_1;
                WRIT_POT_0;
                delay(1);                           //拉低总线3us
                asm("nop");
        asm("nop");
                WRIT_POT_1;                          
                WRIT_DDR_0;
                delay(5);                           //释放总线10us
                temp=(PINB&0x01);
                if(temp!=0x00)
            byte|=0x80;
                if(i<7)byte=byte>>1;
                delay(50);
                 WRIT_DDR_1;                          //此段程序好像有问题
                delay(2);
                asm("nop");
                asm("nop");
        }
        return byte;
}
//============================================

/***********************************
函数名称:DS18B20 写1个字节
函数参数:输入数据、通道号
返 回 值:无       
备    注:无
**********************************/

void ds18b20_write(uchar cmd)
{
  unsigned char i,j;
  WRIT_DDR_1;
  for(j=0;j<=7;j++)
  {
    i=cmd&0x01;
        if(i==0x01)
        {
         WRIT_POT_0;
         delay(5);
         WRIT_POT_1;
         delay(50);
        }
        else
        {
           WRIT_POT_0;
         delay(50);
         WRIT_POT_1;
         delay(5);
        }
        cmd=cmd>>1;
  }
}
//==========================================
//延时程序 (dt)us,晶振(4M);0.25us
void delay(unsigned int dt)
{
   do
   dt--;
   while(dt>1);
}
//===============================================================

使用特权

评论回复
13
gaofei207|  楼主 | 2009-12-23 23:43 | 只看该作者
终于解决了,谢谢大家的帮助!

使用特权

评论回复
14
znmcu| | 2009-12-23 23:51 | 只看该作者
最终是通过什么方法解决的呢,这个是重点

使用特权

评论回复
15
zhuyl456| | 2010-12-4 22:34 | 只看该作者
2# znmcu
问一下,如果真测得是85°c,那该怎么办呢?

使用特权

评论回复
16
lixuan2165| | 2010-12-5 11:44 | 只看该作者
谢谢znmcu的分享,相当规范的代码,学习了。

使用特权

评论回复
17
pnzdx| | 2014-4-20 00:24 | 只看该作者
你好。我最近在做无线温度采集系统,用的也是那个ds18b20这个温度传感器,也是一直显示85,我用单片机开发板的程序,然后自己用又焊接了一个小系统。问题来了,我用开发板的温度传感器就运行正常,可是用自己焊接的温度传感器就一直显示85,所以我猜测是我硬件问题,可是我又试过很多连接方式,可是都不行。大神,如果你有空一定要告诉我啊。我的qq407034569

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:永远不要沉沦,即使有无尽的悲伤,因为你不知道,谁正热恋着你的微笑……

3

主题

36

帖子

1

粉丝