这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » DS18B20驱动

共1条 1/1 1 跳转至

DS18B20驱动

助工
2014-10-15 20:08:29     打赏

.概述


DS18B20是一种单总线数字温度传感器。测试温度范围-55-125,温度数据位可配置为9101112位,对应的刻度值分别为0.50.250.1250.0625,对应的最长转换时间分别为93.75ms187.5ms375ms750ms。出厂默认配置为12位数据,刻度值为0.0625,最长转换时间为750ms。从以上数据可以看出,DS18B20数据位越低、转换时间越短、反应越快、精度越低。


单总线,意味着没有时钟线,只有一根通信线。单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。


需要注意的是,DS18B20和同一系列的DS18S20,在读写上,时序、命令一致,但因温度值存放的位置不一样,对温度数据的处理也不一样,所以程序不能直接套用。


.电路设计


WSF-51DB开发板上,利用AT89S52单片机的P1.1脚来驱动DS18B20,上拉电阻阻值为4.7K欧姆。DS18B20的上拉电阻的阻值是一个需要注意的参数,如果DS18B20放置的位置离电路板较远,需要用较长的电缆来连接时,上拉电阻要相应减小,以弥补线路损耗,而且连接电缆要选用优质的三芯带屏蔽层的电缆,否则不能正常读写数据。


 


                     


                  


.软件设计


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


*程序名称:DS18B20驱动


*程序功能:读写DS18B20,数码管显示温度值,温度值精度为0.1度。




* MCU型号:AT89S52-24PU


*时钟频率:11.0592-12MHZ



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


#include <reg52.h>


#include <intrins.h>


unsigned char tempflag,fraction,tempr;


unsigned char code segmcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};


//共阴极数码管段码0-9


unsigned char code bitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};


//8位共阴极数码管位码


unsigned char code fractioncode[]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};


//DS18B20的小数部分的0-f刻度转换为0-9刻度的查找表,将精度化为0.1


sbit ser=P2^0;//74HC595串行数据输入


sbit oe=P2^1;//74HC595使能


sbit rclk=P2^2; //74HC595数据锁存


sbit srclk=P2^3;// 74HC595串行时钟


sbit DQ=P1^1; //温度总线


 


//延时函数(12MHZ晶振):


void Delayus(unsigned char t)


{  //此函数精确计算:18+6*(t-1)=延时时间(us)


    while(t--);


}


 


//延时ms延时函数:


void Delayms(unsigned int t)


{


       unsigned int i,j;


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


               for(j=0;j<120;j++);


}


 


//任意位数码管显示一个字符函数:


void DTDisplayChar(unsigned char segmd,unsigned char bitd )//数码管段码和数码管位码


{


        unsigned char i;


        unsigned int dat;


        oe=1;//输出为高阻


        dat=bitd;


        dat=dat<<8|segmd; //位码段码合并为一个int型数据


        for(i=0;i<16;i++)//16位数据从高位依次移入74HC595


        {


                 ser=(dat&0x8000)?1:0; //判断最高位,为真取1,为假取0


                 srclk=1;    //上升沿送数据


                 srclk=0;


                 dat<<=1;   //左移取下一位


        }


        rclk=1;//74HC595锁存数据


        rclk=0;


        oe=0;//输出数据


}


 


//DS18B20复位函数:


void Reset18B20(void)


{


        DQ=0;//拉低,开始复位操作


        Delayus(100);//延时至少480us


        DQ=1;//拉高,释放总线控制权


        while(DQ);//等待器件应答(器件拉低),约15-60us


        while(!DQ);//应答脉冲出现后,等待器件拉高,约60-240us


}


//DS18B20写命令函数:


void Write18B20(unsigned char com)


{


        unsigned char i;


        for(i=0;i<8;i++)


        {   


               DQ=0;//开始写操作


               _nop_(); _nop_();//至少延时1us


               DQ=com&0x01;//写数据


               Delayus(2);//延时,器件在45us内采样


               DQ=1;//释放总线控制权


               com>>=1; //右移1位,写下一位


        }


}


 


//DS18B20读数据函数:


unsigned char Read18B20()


{


          unsigned char i,rdata=0;


          for(i=0;i<8;i++)


          {


                   DQ=0;//开始读操作


                   _nop_();_nop_();//至少延时1us


                   DQ=1;//释放总线控制权,15us内要读取数据


                   if(DQ==1) rdata|=0x01<<i;


                   Delayus(10);//延时要大于45us.0时45us后器件才拉高总线


           }


           return rdata;


}


 


//读出温度函数:


 void Read18B20Temperature()


{


        unsigned char templ,temph,temp;


        unsigned int tempv;


        Reset18B20();//复位


        Write18B20(0xcc);//写命令,跳过ROM编码命令


        Write18B20(0x44);//转换命令


     while(!DQ);//等待转换完成


        Reset18B20();//复位


        Write18B20(0xcc);//写命令,跳过ROM编码命令


        Write18B20(0xbe);//读取暂存器字节命令


        templ=Read18B20();//读低字节


        temph=Read18B20();//读高字节


        Reset18B20();//复位


        tempv=temph;


        tempv=tempv<<8|templ;//两个字节合并为一个int型数据


        temp=(unsigned char)(tempv>>4);//去掉小数部分,化成char型数据


        if((temph&0x80)==0x80)//如果是负温度


        {


              tempflag=1; //负号显示


              tempr=~temp+1; //实际温度值为读取值的补码


              fraction=fractioncode[(~templ+1)&0x0f];


//取小数部分补码,将16刻度转换为10刻度,精度为0.1


         }


         else//如果是正温度


         {


                tempflag=0;//正温度,负号不显示


                tempr=temp;//


                fraction=fractioncode[templ&0x0f];


//取小数部分,将16刻度转换为10刻度,精度为0.1


          }     


}


   


//主函数:


int main(void)


{


      tempflag=0;


      while(1)


      {


              Read18B20Temperature();//读取温度值


              DTDisplayChar(segmcode[fraction],0x7f);//显示小数部分


              Delayms(1);


              DTDisplayChar(segmcode[tempr%10]|0x80,0xbf);//显示个位和小数点


              Delayms(1);


              DTDisplayChar(segmcode[tempr%100/10],0xdf);//显示十位


              Delayms(1);


              if(tempflag==1) DTDisplayChar(0x40,0xef);//如果是负温度就显示“-


              else DTDisplayChar(segmcode[tempr/100],0xef);//显示百位


              Delayms(1);


              DTDisplayChar(0xff,0xff);//均衡数码管亮度


      }


      return 0;


}


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]