DS18B20温度采集问题

hedgehog24   2010-4-3 14:36 楼主
#include
#define uchar unsigned char
#define uint  unsigned int
#define jump_ROM  0xCC                 //写跳过读ROM指令。因为只对一个DB18B20操作。
#define start    0x44                                         // 写温度转换指令。
#define read_EEROM 0xBE                                //读暂存器,读内部RAM中9字节的温度
sbit DQ=P3^4;                       //DS18B02唯一与单片机连接的 数据端
uchar TMPH  ,TMPL;                  //用于读取高低 8位数据。
uchar code table[20] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09,0x02, 0x9e, 0x24, 0x0c, 0x98, 0x48, 0x40, 0x1e, 0x00, 0x08};// 前10个(0~9
//)为不加小数点的,         后10个(0~9)为加小数点的,
uchar code table1[3]={0x01,0x02,0x04} ;   //用于数码管的显示。
/****************************************************************************************

     以下为延时函数,晶振为11.0592的时候,延时一次大约为:16us。
*******************************************************************************************/
void delay(us)
{
   uint s;
   for(s=0;s }

/******************************************************************************************       
  一下为复位函数。resert()  并且读取它的信号。  
  注意:一个delay(1)=16us
********************************************************************************************/
uchar  resert(void)
{
   uchar  receive_ready;
   DQ=0;
   delay(32) ;           //最好延时时间为480us。 本次为32*16=512us。
   DQ=1;
   delay(3);             //延时等待。
   receive_ready=DQ;       //获取信号。
    delay(25);             //等待时间隙 完。 不超过480us,本次为400us。
   return  receive_ready;    //返回信号
}


/********************************************************************
* 名称 : read_bit()
* 功能 : 从DS18B20读一个位值
* 输入 : 无
* 输出 : 从DS18B20读出的一个位值
***********************************************************************/
uchar read_bit()
{
    uchar i;
        DQ=0;
        DQ=1;
        for(i=0;i<3;i++);    //从时间隙开始延时15us。
        return  DQ;                    //读出的一个位值返回
}
/********************************************************************
* 名称 : write_bit()
* 功能 : 向DS18B20写一位
* 输入 : bitval(要对DS18B20写入的位值)
* 输出 : 无
***********************************************************************/

void  write_bit(bitval)
{
   
   DQ=0;   //先把数据位置0,开始时间隙。
   //delay(1);        //延时16us。
   if(bitval==1)
   DQ=1;
   delay(5);         //在其余的时间隙保持值。
   DQ=1;

}
/********************************************************************
* 名称 : read_byte()
* 功能 : 从DS18B20读一个字节
* 输入 : 无
* 输出 : 从DS18B20读到的值
***********************************************************************/
uchar  read_byte()
{
    uchar i;
        uchar  value=0;
        for(i=0;i<8;i++)
        {
             if(read_bit())                //当read_bit()=0时,value=0; 当 read_bit()=1时,执行 value|=0x01<                  {
                    value|=0x01<                  
                 
                  }
                  delay(6) ;          //等待剩下时间隙。
       
        }

        return  value;

}

/********************************************************************
* 名称 : write_byte()
* 功能 : 向DS18B20写一个字节
* 输入 : val(要对DS18B20写入的命令值)
* 输出 : 无
***********************************************************************/
void write_byte(uchar val)
{
    uchar i,temp;
        for(i=0;i<8;i++)
        {
             
           temp=val>>i;
           temp=temp&0x01;
           write_bit(temp);
         }
          delay(5);

}

//***********************数据显示程序**************************************
void  display (uchar num ,uchar dat)         //num:第几个数码管。 dat是要显示的数字  
{
    //uchar  i;
        P0=table[dat];
        P2=table1[num];
        delay(800);
        //i=0xff;
        //i=i&(~((0x01)<<(num)) );
   // P2=i;
    //delay(50);



}

//*********************显示温度数值函数t传递的是整形的温度值**************************
void  dis_temp(uint t)
{
    uchar i;
        i=t/100;             //除以100,得到温度的十位。
        display(0,i);             //在第一个数码管上面显示。
        i=t%100/10;          //温度数值的  个位。
        display(1,i+10)        ;    //在第二个数码管上面显示。
        i=t%100%10;          //温度数值的 小数部位
        display(2,i)  ;      //在第三个数码管上面显示。
}

//**************获取温度的数值************************************************
uint  get_temp()
{
   float  f_temp;
   uint temp;
   P2=0x00;
  // resert();                      //通过单总线的所有执行(处理 )都从一个初始化程序开始。其包括总线发出的复位脉冲和{ 从机发出的脉冲。(单机)}
   //write_byte(jump_ROM)  ;        //jump_ROM= 0xCC,  写跳过读ROM指令。因为只对一个DB18B20操作。
   //write_byte(start);                //start 0x44             写温度转换指令。
   //resert();
   write_byte(jump_ROM);                   // 写跳过读ROM指令。因为只对一个DB18B20操作。
   write_byte(read_EEROM);                     //read_EEROM =0xBE    ,读暂存器,读内部RAM中9字节的温度
   TMPL = read_byte();               //读取低字节的8位数据
   TMPH = read_byte();              //读取低字节的8位数据
   temp = TMPH;                     //把高位的8字节数据 付给temp。
   temp <<= 8;                     //两个字节为一个字
   temp = temp | TMPL;
   f_temp=temp*0.0625;               //温度在寄存器里面是12位,分辨率为:0.0625。
   temp=f_temp*10+0.5;                         //扩大10倍为了保存以为小数点。加0.5是为了四舍五入。
   f_temp=f_temp+0.05;
   return   temp;

}


//*****************温度转换函数****************************
void tempchange()
{
    resert();
    delay(50);
        write_byte(jump_ROM);      // 写跳过读ROM指令。因为只对一个DB18B20操作。
        write_byte(start);                   //  写温度转换指令。
    resert();

}

//*****************主函数***********************
void main()
{
   while(1)
   {
               tempchange();            //温度转换函数。
            dis_temp(get_temp()) ;  //  获取温度并且显示
   
   }
       
}

这个采集的不准确,温度也不稳定,老是变化,主要问题可能就是数码管显示出问题了恶霸,硬件是对的。

回复评论 (6)

看看你硬件有没有问题,对于你的程序在检查一下 数据不稳定是很正常的 不过也不至于老是在变化,
点赞  2010-4-3 19:08
对应的DS18B20的上拉电阻 有吧

对于温度不准确,以及不稳定,很可能你对DS18B20的初始化 还有问题,
很可能你的对应时序 控制不对,比如延时不对。

建议楼主百度或GOOGLE下,找下DS18B20的C程序 参考下。
点赞  2010-4-3 19:50
好长程序,没时间看,不过ds18b20我还是用过的
点赞  2010-4-3 23:15
注意:一个delay(1)=16us

这个不对吧。每次调用delay()函数得花多少时间?
点赞  2010-4-4 15:30
楼主我觉得是时序有问题,
ds18b20对时序要求很严格的
点赞  2010-4-4 16:52

基于DS18B20的多点测温系统

要求该系统中有RS232、IIC、SPI、单总线协议的芯片,实现多点测温。要求系统有时钟芯片,存储芯片(固定间隔时间内采集的温度值),温度传感器、串口、液晶,声光报警。液晶显示内容包括各点温度,报警温度,时间。能够通过串口修改报警温度。
点赞  2012-5-27 20:45
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复