bmfw 发表于 2009-11-19 22:52

请教一个关于DS18B20如何正确读数的问题?

小弟用DS18B20进行温度采集。在室内测量,显示零下四十多度,虽然最近天气比较冷,可也没有这么低呀!当把DS18B20用手握住(或用空调吹一会儿),过一会儿,如果测量到的温度显示》16时时就没问题,这是怎么回事?

bmfw 发表于 2009-11-19 22:53

从零下40多突然到16,变化也太大了

smileagain 发表于 2009-11-19 23:42

我估计是你读出的数据没有正确解码。符号位你是怎么处理的?再看一下datasheet里的那张表吧

xwj 发表于 2009-11-20 00:27

呵呵,
LZ对自己的程序太有自信了,这么相信你的读数啊?

bmfw 发表于 2009-11-20 19:36

本帖最后由 bmfw 于 2009-11-25 21:35 编辑

附上有关程序,帮我看一下!
//////无符号整数转换为BCD码//////////////////////
uchar IntToBcd(unsigned char Int)
{
uchar i,j;
j=100;
i=0;
while((Int >= j) && (j>9))
    {
      Int-=j;
      i++;
    }
j/=10;
i=0;
while((Int >= j) && (j>9))
    {
      Int-= j;
      i++;
    }
return((i<<4)|(Int));
}
/////////////////////////////////////////////////
voidGetTemperature(void)
{
uchar TempH = 0;
uchar TempL = 0;
uchar TempSigned= 0;
uchar TempHigh= 0;
uchar TempLow = 0;
DS18B20_IO = 1;
if(DS18B20_Init())      //接收到应答脉冲
    {
      DS18B20_WriteByte(SkipRom);//0xcc发出SKIP ROM命令
      DS18B20_WriteByte(ConvertTemperature);//0x0x44发送温度转换命令
      Delay15us(50);      //等待AD转换结束
      DS18B20_Init();
      DS18B20_WriteByte(SkipRom);       //0xcc发出SKIP ROM命令
      DS18B20_WriteByte(ReadScratchpad);//0xbe发送读命令
      TempL = DS18B20_ReadByte();       //读取温度值低位字节(其中低4 位为二进制的"小数"部分)
      TempH = DS18B20_ReadByte();       //读取温度值高位字节(其中高5位为符号位)
      if (TempH^3==0) { TempSigned = 0;}//温度的符号位,0为正温度,1为负温度
      else                              //负温度
      {
          TempSigned = 1;               //温度的符号位,0为正温度,1为负温度
          TempL=256-TempL;            //负温度用补码表示,即反码加1
          TempH=255-TempH;            //也就是255-Temp+1
      }
    }
//TempH的低四位和TempL的高四位是整数部分,TempL的低四位是小数部分
TempHigh= IntToBcd((TempH<<4)|(TempL>>4));
TempLow   = IntToBcd((TempL&0x0f)*625/100);//小数部分*625/100转换成整数
}

ningling_21 发表于 2009-11-21 09:42

温度正负判断好像错了.

bmfw 发表于 2009-11-21 20:46

昨晚测试了一下,读出的十六进制是正确的,可能是IntToBcd出了问题

bmfw 发表于 2009-11-25 21:28

本帖最后由 bmfw 于 2009-11-25 21:33 编辑

再次请问一下,为什么我的程序在16度以下不能正确解码16度以上却没有问题?有关程序如下
uchar TAB_IntToBcd[]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,};
TempL = DS18B20_ReadByte();//读取温度值低位字节(其中低4 位为二进制的"小数"部分)
TempH = DS18B20_ReadByte();//读取温度值高位字节(其中高5位为符号位)
if (TempH^3==0)   //正温度
{
    TemSigned = 0x00; //温度的符号位,0为正温度,1为负温度
}
else            //负温度
{
    TemSigned = 0x01;
    TempL=256-TempL;            //负温度用补码表示,即反码加1
    TempH=255-TempH;            //也就是255-Temp+1
}
//TempH的低四位和TempL的高四位是整数部分,TempL的低四位是小数部分
TemHigh= TAB_IntToBcd[(TempH<<4)|(TempL>>4)];
TemLow   = TAB_IntToBcd[(TempL&0x0f)*625/100];//小数部分*625/100转换成整数

zlh6630 发表于 2009-12-1 17:26

我写了个在0到16度能正常测温,16度以上就跳到0了,我知道是高温数据没读到,但程序还没找到问题

bmfw 发表于 2009-12-9 16:09

能把有关程序附上吗?

不亦心 发表于 2009-12-9 20:18

汇编的源程序要嘛

wi2c 发表于 2009-12-9 22:33

回去仔细读手册
DS1820很成熟
绝对没有问题
你自己完全可以搞定,你行的

znmcu 发表于 2009-12-18 15:33

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)=DS18B20_ReadByte();
((unsigned char *)&t)=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

传感时代 发表于 2019-9-27 22:48

可选用成品,我们专门研发了一线总线采集模块LCT2662M,还有仪表LCT2201C,可以采集常用的一线总线器件ds18b20,还有模拟量ds2438等。支持64个ds18b20同时采集。输出rs485总线,便于和电脑等终端通讯,常用于粮库粮仓测温,煤筒仓测温,水蓄冷测温等等。

https://bbs.21ic.com/data/attachment/forum/201909/27/224119qh33pe2hzyzm0meh.jpg.thumb.jpg https://bbs.21ic.com/data/attachment/forum/201909/27/224418kc1qznvvuvnc619r.jpg.thumb.jpg
https://bbs.21ic.com/data/attachment/forum/201909/27/224505i0i55yd0zh99ipq6.jpg.thumb.jpg
页: [1]
查看完整版本: 请教一个关于DS18B20如何正确读数的问题?