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

[复制链接]
8544|13
 楼主| bmfw 发表于 2009-11-19 22:52 | 显示全部楼层 |阅读模式
小弟用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));
}
/////////////////////////////////////////////////
void  GetTemperature(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

  1. #include "DS18b20.h"
  2. #include "myfun.h"

  3. /*******************************************************

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

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

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

  25. unsigned char DS18B20_Init()
  26. {
  27. unsigned char x=0;
  28. DQ=1;       //DQ复位
  29. delay(96);  //稍做延时
  30. DQ=0;       //单片机将DQ拉低
  31. delay(960); //精确延时 大于 480us
  32. DQ=1;       //拉高总线
  33. delay(168);
  34. x=DQ;       //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  35. delay(240);
  36. return x;
  37. }

  38. /******************************************************************
  39. - 功能描述:从DS18B20读取一个字节
  40. - 隶属模块:DS18B20模块
  41. - 函数属性:内部
  42. - 参数说明:无      
  43. - 返回说明:从DS18B20读到的字节
  44. - 注:无
  45. ******************************************************************/

  46. unsigned char DS18B20_ReadByte()
  47. {
  48. unsigned char i=0,dat=0;
  49. for(i=0;i<8;i++)
  50. {
  51.   DQ=0;    //给脉冲信号
  52.   dat>>=1;
  53.   DQ = 1;  //给脉冲信号
  54.   if(DQ) dat|=0x80;
  55.   delay(48);
  56. }
  57. return(dat);
  58. }

  59. /******************************************************************
  60. - 功能描述:向DS18B20写入一个字节
  61. - 隶属模块:DS18B20模块
  62. - 函数属性:内部
  63. - 参数说明:dat:将要向DS18B20写入字节      
  64. - 返回说明:无
  65. - 注:无
  66. ******************************************************************/

  67. void DS18B20_WriteByte(unsigned char dat)
  68. {
  69. unsigned char i=0;
  70. for(i=0;i<8;i++)
  71. {
  72.   DQ=0;
  73.   DQ=dat&0x01;
  74.   delay(60);
  75.   DQ=1;
  76.   dat>>=1;
  77. }
  78. }

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

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

  1. #ifndef  _DS18B20_H_
  2. #define  _DS18B20_H_

  3. #include "reg51.h"

  4. /*******************************************************

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

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

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

  19. unsigned char DS18B20_Init();
  20. unsigned char DS18B20_ReadByte();
  21. void DS18B20_WriteByte(unsigned char dat);
  22. unsigned int DS18B20_ReadTemperature();

  23. #endif
传感时代 发表于 2019-9-27 22:48 | 显示全部楼层
可选用成品,我们专门研发了一线总线采集模块LCT2662M,还有仪表LCT2201C,可以采集常用的一线总线器件ds18b20,还有模拟量ds2438等。支持64个ds18b20同时采集。输出rs485总线,便于和电脑等终端通讯,常用于粮库粮仓测温,煤筒仓测温,水蓄冷测温等等。



您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

86

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部