×
单片机 > 单片机程序设计 > 详情

51单片机驱动DS18B20温度传感器程序及心得

发布时间:2020-06-08 发布时间:
|
关于DS18B20温度传感器,在没有硬件设备的辅助下,写内部程序有些困难,因为看不到实际信号波形。对于单片机,我。。。渐渐的有些心灰意冷。。虽然掌握了1_WIRE总线,却少了很多喜悦,下雨了。。。它是我的爱好,我付出了很多,可是我看不到实际的前景。。以我个人之力,要步入尖端芯片领域,很困难,在这里,采棉花是个普遍性的大问题,大型机械设备缺陷很多,如果以微控制芯片提高精度,我想效益会相当可观,可是技术瓶颈难以逾越。。。硬件研发,失败了,所有投入赴之东流,成功了,回报丰厚。现在,各行各业都处于饱和,没有成熟先进的技术,很难有立足之地,,,,,我开始重新审视我的选择。。。。。。艰难。。

    /*
  建立时间: 2013年5月2日;
   
 前言:  我用软件仿真,测算延时时间,效果不错,但是根据教程,复位时,先释放总线
     (wd高电平),然后主机拉低wd,持续时间为400--960微妙.后主机拉高wd,持续15-
  60微妙,后 从机,会拉低电平持续时间是60--240微妙(此时表示复位成功),如果
  从机没有将总线拉低,则复位失败.然后,主机拉高电平60--240微妙.复位结束;
      可,实验证明,在,从机,拉低总线电平后,持续一定时间,从机还会将总线拉高!这
   是教程中的一个重大错误!
   temperature sensor reset module finishing time:  23:08:00 
     (   温度     传感器  复位  模块     完成    时间  )
  temperature sensor  操作过程:
  1. reset DS18B20;
        2. 发出Skip ROM 命令(CCH); (跳跃ROM命令)
  3. 发出Convert T命令(44H); (温度转换命令)
  4. reset DS18B20;
  5. 发出Skip ROM命令(CCH);(跳跃ROM命令)
  6. 发出读取命令(BEH);
  7. 读出两个字节的温度;
  8. 温度格式转换;
  
    2013年5月8日22:56:44
 
  DS18B20 Temperature sensor read data module accomplish;
   (     温度    传感器 读   数据  模块    完成   )
 
  现在还有温度显示模块没有完成,硬件是1602液晶屏......
 2013年5月9日19:32:31
   今天,温度传感器的程序主体结构全部完成!!!!!
 不容易啊,值得庆祝一下!!!!!!
 一共写了7天程序!{陆陆续续};
 喝个  品酸乳果汁.......
*/
#include
typedef unsigned char uint8 ;
typedef unsigned int uint16;

sbit wd = P3^2;  //定义数据单总线;
sbit e =P1^5; // 定义1602液晶显示器数据使能端口;
sbit rs=P1^0; // 定义数据/指令选择端口;
sbit rw=P1^1; // 定义  读/写  选择端口;
sbit BF=P0^7; // 定义繁忙位;
bit w=0;  //定义一个全局一位变量;
 
//===========1602液晶显示器模块;===============
busy() //液晶屏繁忙检测函数;
{ e=0;
    rs=0;
 rw=0;
   P0=0xff;
  do
  { e=0;   //使能位清零;
    rs=0;   //指令;
 rw=1;   //读;
 e=1;   //数据传输启动;
  }while(BF); //如果BF==0;则液晶处于空闲状态;
   e=0;
}
play_data(uint8 wr) //液晶写入数据;
{
   busy();   //繁忙检测;
   P0=wr;   //装载数据;
   rs=1;   //数据;
   rw=0;   //写入;
   e=1;    //传输开始;
   e=0;       //传输结束;
}
play_cmd(uint8 cmd)  //液晶写入指令;
{
  busy(); //繁忙检测;
  P0=cmd; //装载数据;
  rs=0;     //指令;
  rw=0;     //写入;
  e=1;      //传输开始;
  e=0;      //传输结束;
}
reset_1602()   //1602液晶显示器初始化函数;
{
  play_cmd(0x38);
  play_cmd(0x0c);
  play_cmd(0x06);
  play_cmd(0x01);

}

//=========温度传感器延时模块============================

// sbit led= P1^0;
delay(uint8 num )   //如果unm等于1;延时16.28微妙;

   while(num--);  //如果num大于一,则16.28+(num-1)*6.51.
}
delay2()    //此函数延时3.26微秒;
{
   uint8 j=0;
    j=9;
 
 
}

delay3()
{
   uint16 s=60000;
   while(s--);
 
 
}[page]

reset_1820()  //========复位温度传感器; ========
{
 
  while(wd)
  {
   wd=1;
   delay(140);   //拉高总线,延时大概921微妙左右;(延时值自定);
   wd=0;    //总线由单片机拉低,下为延时函数,大概800微秒左右;
   delay(61);  //1个此函数会延时400微妙左右;
   delay(61);  //两个是800微妙左右;
   wd=1;    //主机拉高总线,68微秒左右;
   delay(9);      //延时68微妙左右
   if(wd==0)      //如果wd是0就终止复位;(代表复位成功);
    {
       while(wd==0);   //总线一旦为低,那么就等待从机再将总线拉高.
    break;    //终止while循环;(reset function end)
    }
   else
     {
     wd=1;
     delay(20);    //延时140微妙;
  }   
   }
      delay(30); //此时总线为高电平并延时205微妙,复位成功!;
  // if(wd)led=0;//此语句为检验是否复位成功;P1^0外接9012三极管接led小灯;
}
 
write_byte(uint8 dat)

    uint8 i=0;
    
 for(i=0;i<8;i++)
      { 
      wd=0;      //A点;
   delay2(); //延时
      wd=dat & 0x01;
      dat>>=1;
  
   delay(6);  //A点到此处用时65.11微秒;
   wd=1;   //总线释放;
   delay2();  //延时3.26微秒;
   }
 }   //========此函数执行完成之后总线为高电平;

uint8  read_byte() //=====读8位数据;===================
{
 uint8 j=0,  dat =0;
 
    for(j=0;j<8;j++)
  {
     dat>>=1;
   wd=0;  // A点  mcu拉低电平3.26微秒;
  delay2();   // 延时3.26微秒;
  wd=1;  
  if(wd)
   {
     dat|=0x80;
   }      //读完数据后A点到此处是11.93微秒,保持在15微秒之内;
   delay(9);   // A点到此处80.29微秒; 理想时间范围是60--120微秒;
   wd=1;  //释放总线;
   delay2();  //延时3.26微秒;
  }
 
   return dat;

}

start_sensor()    //启动传感器;
{
  reset_1820();
  write_byte(0xcc);  //跳跃命令;
  write_byte(0x44);  //转换temperature(温度)命令;
}
uint8 read_temp()   //从温度传感器度温度数据过程;
{
  uint8 ak[2];
  uint16  dat=0 , j=0;
    reset_1820();   //复位温度传感器
    write_byte(0xcc);  //跳跃rom命令;
    write_byte(0xbe) ;  // 发出读数据命令;
    ak[0]=read_byte(); //读取第一个字节数据;
    ak[1]=read_byte(); //读取第二个字节数据;
    dat=ak[1];    //要把两个八位数据载入1个16位变量里;
    dat<<=8;
    dat|=ak[0];
       j= dat;

  //==========以下是把温度传感器内部数据编译成16进制编码;
     if((j>>11)==0x1f) //此语句是负温度进入.0x1f是二进制5个全1;
  {
  dat=(~dat)+1;    //负温度要取反加一操作; 
  dat/=16;    //传感器给的温度系数要除以16后,得到的数才是常规温度系数;
  w=0;   //此语句是在主函数中用来判断是正温度还是负温度;
  return dat;  //向主函数返回数据,并终止函数;
  }
     j=dat;
   if((j>>11)==0)   //如果是零则是正温度;
     {
     dat/=16;    //数据直接除以16,就得到了常规温度系数;
     w=1;     //1代表正;
     return dat; //向主函数返回数据,并终止函数;
  
  }
 
   return 130;  //向主函数返回数据,并终止函数;
   
}

delay_ms()  //延时1秒;
{
  uint8 i=250;
  uint16 j=608;
   while(j--)
    { while(i--);
       i=250;
      
    }
 
}
 
error()  //测温出错;
{
   uint8 i=5, j=0 ,ak[]="Error!";
 
 while(i--)
 {
     play_cmd(0x82);
     while(ak[j]!='')
   {
     play_data(ak[j++]);
   }  j=0;
      delay3();
     play_cmd(0x01);
     delay3();  
 }   
}

main()
{

  uint8 dat=0 ,j=3,len=0 ,num[]="start.....";
 
  reset_1602();
 
 while(j--)    //这是启动电源时,液晶显示:start....(并闪烁3次)
 {   play_cmd(0x82);
    while(num[len]!='')
     {
     play_data(num[len++]);  
  } 
       len=0;
       delay3();
       play_cmd(0x01);
       delay3();
 }
 
 
 
 while(1)
   {    
     start_sensor();   //启动温度传感器;
  delay_ms();    //等待1秒;
  dat = read_temp(); //读取温度数据并赋给dat变量;
  
   if(dat==130)    //如果返回来的数据是130,表明采集温度出错;
   {
     error();
   }
  else if(w==1)  //如果w是1,就代表正温度.输出;
   {
     play_cmd(0x83);
    play_data(dat/10+'0');
    play_data(dat%10+'0');
   }
   else    //否则,就是负温度,输出时前面加一个负号;
     {
    play_cmd(0x82);
    play_data('-');
    play_data(dat/10+'0');
    play_data(dat%10+'0');
  }
  
   } //我的亲娘四舅奶奶啊!!!!!!终于完成了!!!!2013年5月9日19:32:10
 
  
    
}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式