温度计的设计,(使用DS18B20)

2025-01-03 05:44:22
推荐回答(1个)
回答1:

#include 

#include     //Keil library  

#include    //Keil library

#include 

#define uchar unsigned char 

#define uint unsigned int

#define display1  0x01      //数码管1从左至右

#define display2  0x02    //数码管2从左至右

#define display3  0x04     //数码管3从左至右

#define display4  0x08  //数码管4从左至右

#define display5  0x10   //数码管5从左至右

#define display6  0x20  //数码管6从左至右

#define display7  0x40      //数码管7从左至右

#define display8  0x80  //数码管8从左至右

sbit led=P1^5;

sbit TMDAT=P3^6;          //根据实实际情况设定

sbit set=P1^0;//设定

sbit up=P1^1;//加

sbit down=P3^2;//减

uchar tempint,f,bb,tempth,settemp; //温度整数部分和小数部分

float wendu;

int tempdf,c;

    code unsigned char ledmap[]={0xc0,0xf9,0xa4,0xb0,0x99,

                               0x92,0x82,0xf8,0x80,0x90,0xbf};

    code unsigned char ledmap1[]={0x40,0x79,0x24,0x30,

                                 0x19,0x12,0x02,0x78,0x00,0x10};

                                 //7段数码管0~9数字的共阳显示代码和负号位代码(最后一位)

void set_ds18b20();                   //初始化DS18B20子程序

void get_temperature();               //获得温度子程序

void read_ds18b20();                  //读DS18B20子程序

void write_ds18b20(uchar command);    //向DS18B20写1字节子程序

void delayms(uchar count);            //延时count毫秒子程序

void disp_temp(tempint,tempdf);     //显示温度子程序

//***********************初始化DS18B20子程序**********************************

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

void set_ds18b20()

{

    while(1)

    { 

        uchar delay,flag;

        flag=0;

        TMDAT=1;

        delay=1;

  while(--delay);

        TMDAT=0;                  //数据线置低电平

        delay=250;

        while(--delay);          //低电平保持500us

        TMDAT=1;                  //数据线置高电平

        delay=30;

        while(--delay);          //高电平保持60us

        while(TMDAT==0)          //判断DS18B20是否发出低电平信号

        {

            delay=210;            //DS18B20响应,延时420us

            while(--delay);

            if(TMDAT)             //DS18B20发出高电平初始化成功,返回

            {

                flag=1;             //DS18B20初始化成功标志

               

               //初始化成功LED标志

    

                break;

            }

        }

        if(flag)                  //初始化成功,再延时480us,时序要求

        {

            delay=240;

            while(--delay);

            break;

        }

    }

}

//***********************获得温度子程序***************************************

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

void get_temperature()            //温度转换、获得温度子程序

{

    set_ds18b20();                //初始化DS18B20

    write_ds18b20(0xcc);          //发跳过ROM匹配命令

    write_ds18b20(0x44);          //发温度转换命令

    disp_temp(tempint,tempdf);                  //显示温度,等待AD转换

    set_ds18b20();

    write_ds18b20(0xcc);          //发跳过ROM匹配命令

    write_ds18b20(0xbe);          //发出读温度命令

    read_ds18b20();               //将读出的温度数据保存到tempint和tempdf处

}

//***********************读DS18B20子程序***************************************

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

void read_ds18b20()

{

    uchar delay,i,j,k,temp,temph,templ;

    float wendu;

    j=3;                          //读2位字节数据

    do

    {

    for(i=8;i>0;i--)              //一个字节分8位读取

    {

        temp>>=1;                 //读取1位右移1位

        TMDAT=0;                  //数据线置低电平

        delay=1;

  while(--delay);

        TMDAT=1;                  //数据线置高电平

        delay=4;

        while(--delay);          //延时8us

        if(TMDAT)                 //读取1位数据

            temp|=0x80;      

        delay=25;                 //读取1位数据后延时50us

        while(--delay);

    }

    if(j==3)                      

        templ=temp;//读取的第一字节存templ

         

     if(j==2) 

        temph=temp;  //读取的第二字节存temph

    if(j==1)  

        tempth=temp;   //读取的第3字节存tempth   TH的值         

    }while(--j);

    f=0;

    if((temph & 0xf8)!=0x00)  //若温度为负的处理,对二进制补码的处理

    {

        f=1;    //为负温度f置1

 

        temph=~temph;

        templ=~templ;        

  k=templ+1;

        templ=k;

        if(k>255)

        {

           temph++;

        }

    }

    tempdf=templ & 0x0f;          //将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf

         c=(tempdf*625);

         tempdf=c;

    templ>>=4;  //

    temph<<=4; //转化成字节温度

    tempint=temph|templ;//两字节合并为一个字节

   //wendu=((temph*256)+templ)*0.0625; 

   // tempdf=templ & 0x0f;          //将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf

     // if (tempdf&0x08==1) a=8;

         //if (tempdf&0x04==1) b=4;

        // if (tempdf&0x02==1) c=2;

        // if (tempdf&0x01==1) d=1;

  // tempdf=a+b+c+d;

        // c=tempdf*625;

         //tempdf=c;

    //templ>>=4;  //

    //<<=4; //转化成字节温度

   // tempint=temph|templ;//两字节合并为一个字节

}

//***********************写DS18B20子程序***************************************

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

void write_ds18b20(uchar command)

{

    uchar delay,i;

    for(i=8;i>0;i--)              //将一字节数据一位一位写入

    {

        TMDAT=0;                  //数据线置低电平

        delay=6;                  //延时12us

        while(--delay);

        TMDAT=command&0x01;       //将数据放置在数据线上

        delay=25;                 //延时50us

        while(--delay);

        command=command>>1;       //准备发送下一位数据

        TMDAT=1;                  //发送完一位数据,数据线置高电平

    }

}

//***********************显示子程序***************************************

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

void disp_temp( tempint,tempdf)

{

     uchar tempinth,tempintl,tempinbai,shifen,baifen,gefen,qianfen;

           

    

           int x;

      

  for(x=0;x<10;x++)          

           {   

     if (bb!=0)

     {  tempint=settemp;

        tempdf=0;

     } 

     else

     { tempinbai=tempint/100; 

        tempinth=(tempint%100)/10;         

        tempintl=tempint%10;         //整数取模

           gefen=tempdf/1000;

           shifen=tempdf%1000/100; 

           baifen =tempdf%100/10; 

           qianfen=tempdf%10; //小数取模

     }

    

   if (f==0)

   { 

  

            P0=display1; //符号位

              P2=ledmap[0];

     }

  else 

  {

            P0=display1; //符号位

              P2=ledmap[10];

  }

           delayms(2);

        P0=display2; 

              P2=ledmap[tempinbai];  //开百位           

           delayms(2);

           P0=display3;  

              P2=ledmap[tempinth];//开十位                   

           delayms(2);

          P0=display4;

             P2=ledmap1[tempintl]; //开个位 

           delayms(2);

          P0=display5;

             P2=ledmap[gefen];//开个分位  

          delayms(2);

        P0=display6; 

             P2=ledmap[shifen]; //开十分位

          delayms(2);

       P0=display7;

            P2=ledmap[baifen]; //开百分位  

          delayms(2);

         P0=display8;  

            P2=ledmap[qianfen];//开千分位                

           

          }

       

      }

 

//***********************延时count ms子程序***************************************

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

void delayms(uchar count)  //延时count ms子程序

{

    uchar i,j;

    do

    {

        for(i=5;i>0;i--)

        for(j=98;j>0;j--);

    }while(--count);

}

//***********************键盘扫描子程序***************************************

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

void keyscan()  //键盘扫描               

  {

    

    if(set==0)

    { 

       delayms(1);

    }

         if(set==0)

    {  

     

     bb++;      

                 while(!set); //循环在此 非0=1 

    } 

          if(bb==1)

        {  

      

       

         if(up==0)

     {

     delayms(1);

      }

      if(up==0) 

      {   

      

                      disp_temp(settemp);

        if(settemp<125)

             {settemp++;}

       while(!up)//非0=1       

                  {

       disp_temp(settemp);

      }

                }

          if(down==0)

       {

        delayms(1);

       }

       if(down==0) 

       {  

               disp_temp();

      if(settemp!=0) //不等于0为真执行

         {

      settemp--;

       while(!down) // down为(非0=1)循环执行         

         {

         disp_temp(settemp);

       }

      }

        }

                }

    

            if(bb==2)

             {bb=0;

       set_ds18b20();                //初始化DS18B20

       write_ds18b20(0xcc);          //发跳过ROM匹配命令

       write_ds18b20(0x4e);          //发温度转换命令

       write_ds18b20(settemp);        //写TH 3

    //write_ds18b20(settemp);   写到TL  4

   // write_ds18b20(settemp);    写分辨率  5   

       set_ds18b20();                //初始化DS18B20

       write_ds18b20(0xcc);          //发跳过ROM匹配命令

      write_ds18b20(0x48); 

}}

void main()

{     set_ds18b20();

     write_ds18b20(0xcc);          //发跳过ROM匹配命令

     write_ds18b20(0xbe);          //发出读温度命令

     read_ds18b20();               //将读出的数据

     settemp=tempth;                //将TH读到单片机

     SP=0x60;                     //设置堆栈指针

  bb=0;

  led=0;

     while(1)

     {      

   if(bb==0)

     {     keyscan();

            get_temperature();       //获得温度

     }

   

         disp_temp(tempint,tempdf);             //显示温度

     }

}