您现在的位置是:首页 > 电路图 > 电路图

基于D18B20的数字温度计

转载来源:电子技术应用-AET chinaaet.com 电子发烧友 elecfans.com2017-03-16

简介以前做过的东西都放在了电脑上或传给自己的朋友参考,想到还有很多不相识的朋友还在单片机的门前徘徊,基于此想法,有必要将我的入门级作品粘到这里与大家分享,让我们在嵌入

以前做过的东西都放在了电脑上或传给自己的朋友参考,想到还有很多不相识的朋友还在单片机的门前徘徊,基于此想法,有必要将我的入门级作品粘到这里与大家分享,让我们在嵌入式技术的道路上走的更远些,年轻人将自己的爱好变为自己的事业应该是一件很幸福的事情.....     由于有仿真图形,各个管脚的配置情况是很清楚地,也就不说了,先把仿真图发上:

下面是源代码,注释也算详尽,我还会在最后附上作品实物,其实仿真通过了,一般情况下就通过了:
//=======================================================================================
//  作者: li ran                     
//  描述:数字温度计
//日期:2009、x、x
//=======================================================================================
 #include "reg52.h"
 #include "intrins.h" //_nop_();延时函数用
 #define uchar unsigned char
 #define uint unsigned int
 uint count;
 sbit DQ=P3^2; //温度输入口
 sbit DIN=P0^7; //LED小数点控制
 sbit aa=P2^0;
 sbit bb=P2^1;
 sbit cc=P2^2;
 sbit dd=P2^3;
 sbit ee=P2^4;
 uchar code tab1[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40}; //共阳LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"
 uchar code tab2[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
 uchar data temp_data[2]={0x00,0x00}; // 读出温度低8位,高8位
 uchar t0,t1,t2,t3,t4;//显示单元数据,共4个数据,t4运算暂存用
  /***********11us延时函数**********/
  void delay1(uint t)
   {
     for(;t>0;t--);
   }
 /***********显示扫描函数**********/
  void scan()
  {
     P0=tab1[t3];
     aa=0;
  delay1(90);
     P2=0xff;
  P0=tab1[t2];
     bb=0;
  delay1(90);
  P2=0xff;
  P0=tab1[t1];
  DIN=1;
  cc=0;
  delay1(90);
  P2=0xff;
  P0=tab1[t0];
  dd=0;
  delay1(90);
  P2=0xff;
  }
  /***********18B20复位函数**********/
  void ow_reset(void)
  {
    char presence=1;
    while(presence)
  {
   while(presence)
    {
      DQ=1;_nop_();_nop_();
    DQ=0; //
    delay1(50); // 550us
    DQ=1; //
    delay1(6); // 66us
    presence=DQ; //
     }
    delay1(45); //延时500us
     presence = ~DQ;
  }
  DQ=1;
 }
/**********18B20写命令函数*********/
//向总线上写一个字节
void write_byte(uchar val)
{ uchar i;
 for (i=8; i>0; i--) //
   {
     DQ=1;_nop_();_nop_();
  DQ = 0;
  _nop_();_nop_();_nop_();_nop_();_nop_();//5us
    DQ = val&0x01; //最低位移出
    delay1(6); //66us
    val=val/2; //右移一位
   }
   DQ = 1;
   delay1(1);
}
/*********18B20读1个字节函数********/
//从总线上读取一个字节
 uchar read_byte(void)
  { uchar i;
   uchar value = 0;
    for (i=8;i>0;i--)
 { DQ=1;_nop_();_nop_();
  value>>=1;
  DQ = 0; //
  _nop_();_nop_();_nop_();_nop_(); //4us
  DQ = 1;_nop_();_nop_();_nop_();_nop_(); //4us
  if(DQ)value|=0x80; delay1(6); //66us
 }
  DQ=1;
  return(value);
  }
  /***********读出温度函数**********/
   void read_temp()
    { ow_reset(); //总线复位
      write_byte(0xCC); // 跳过Skip ROM命令
      write_byte(0xBE); // 发读命令
   temp_data[0]=read_byte(); //温度低8位
   temp_data[1]=read_byte(); //温度高8位
   ow_reset();
   write_byte(0xCC); // 跳过
   write_byte(0x44); // 发转换命令
     }
/***********温度数据处理函数**********/
 void work_temp()
 { uchar n=0; //
  if(temp_data[1]>127)
    {
  temp_data[1]=(255-temp_data[1]);//我也不明白为啥256就不行,但是用255显示负温度的时候有点误差
  temp_data[0]=(255-temp_data[0]);
  n=1;
 }//负温度求补码
 t4=temp_data[0]&0x0f;
 t0=tab2[t4]; //小数部分
 t4=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);// 整数部分
 t3=t4/100; //百位
 t1=t4%100;
 t2=t1/10; //十位
 t1=t1%10; //个位
 if(!t3)
 {
  t3=0x0A;
 if(!t2)
  {
   t2=0x0A;
  }
 }//最高位为0时都不显示
 if(n)
  {
     t3=0x0B;//负温度时最高位显示"-"
  }
}
/**************主函数****************/
  void main()
  {
     uint h;
         TMOD=0X01;               //定时器的设置
   TH0=(65536-1000)/256;         //
   TL0=(65536-1000)%256;         //
   EA=1;                          //
   ET0=1;                          //
   TR0=1;                          //
   //EA=0;
  ow_reset(); // 开机先转换一次
  write_byte(0xCC); // Skip ROM
   write_byte(0x44); // 发转换命令
   for(h=0;h<33000;h++)
   {P0=0xbf;P2=0x00;P1=0xbf;P2=0x00;} //开机显示"0000"2秒
    while(1)
     {
  
   read_temp(); //读出18B20温度数据 ??
    work_temp(); //处理温度数据 ??
     for(h=0;h<300;h++)
      {scan();} //显示温度值1秒
  }
  }
  //定时中断函数的入口
  void time0() interrupt 1
{
 TH0=(65536-1400)/256;
 TL0=(65536-1400)%256;
 count++;
 if(count<700){P1=0x6f;ee=0;} //这些if语句是用来控制最左边数码管的闪烁速度的
 //(一个女孩名字的第一个字母)O(∩_∩)O哈哈~
 if((700<count)&&(count<=1400)){P1=0x00;ee=0;}
 if((1400<count)&&(count<=2100)){P1=0x67;ee=0;}
 if((2100<count)&&(count<=2800)){P1=0x00;ee=0;}
 if((2800<count)&&(count<3500)){P1=0x67;ee=0;}
 if((4200<count)&&(count<=4900)){P1=0x00;ee=0;}
 if(count>5000){count=0;}

}