專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

51單片機(jī)驅(qū)動(dòng)DS18B20溫度傳感器程序及心得

作者:huqin   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年02月28日   【字體:

   關(guān)于DS18B20溫度傳感器,在沒(méi)有硬件設(shè)備的輔助下,寫內(nèi)部程序有些困難,因?yàn)榭床坏綄?shí)際信號(hào)波形。對(duì)于單片機(jī),我。。。漸漸的有些心灰意冷。。雖然掌握了1_WIRE總線,卻少了很多喜悅,下雨了。。。它是我的愛(ài)好,我付出了很多,可是我看不到實(shí)際的前景。。以我個(gè)人之力,要步入尖端芯片領(lǐng)域,很困難,在這里,采棉花是個(gè)普遍性的大問(wèn)題,大型機(jī)械設(shè)備缺陷很多,如果以微控制芯片提高精度,我想效益會(huì)相當(dāng)可觀,可是技術(shù)瓶頸難以逾越。。。硬件研發(fā),失敗了,所有投入赴之東流,成功了,回報(bào)豐厚,F(xiàn)在,各行各業(yè)都處于飽和,沒(méi)有成熟先進(jìn)的技術(shù),很難有立足之地,,,,,我開(kāi)始重新審視我的選擇。。。。。。艱難。。
    /*
  建立時(shí)間: 2013年5月2日;
  
 前言:  我用軟件仿真,測(cè)算延時(shí)時(shí)間,效果不錯(cuò),但是根據(jù)教程,復(fù)位時(shí),先釋放總線
     (wd高電平),然后主機(jī)拉低wd,持續(xù)時(shí)間為400--960微妙.后主機(jī)拉高wd,持續(xù)15-
  60微妙,后 從機(jī),會(huì)拉低電平持續(xù)時(shí)間是60--240微妙(此時(shí)表示復(fù)位成功),如果
  從機(jī)沒(méi)有將總線拉低,則復(fù)位失敗.然后,主機(jī)拉高電平60--240微妙.復(fù)位結(jié)束;
      可,實(shí)驗(yàn)證明,在,從機(jī),拉低總線電平后,持續(xù)一定時(shí)間,從機(jī)還會(huì)將總線拉高!這
   是教程中的一個(gè)重大錯(cuò)誤!
   temperature sensor reset module finishing time:  23:08:00
     (   溫度     傳感器  復(fù)位  模塊     完成    時(shí)間  )
  temperature sensor  操作過(guò)程:
  1. reset DS18B20;
        2. 發(fā)出Skip ROM 命令(CCH); (跳躍ROM命令)
  3. 發(fā)出Convert T命令(44H); (溫度轉(zhuǎn)換命令)
  4. reset DS18B20;
  5. 發(fā)出Skip ROM命令(CCH);(跳躍ROM命令)
  6. 發(fā)出讀取命令(BEH);
  7. 讀出兩個(gè)字節(jié)的溫度;
  8. 溫度格式轉(zhuǎn)換;
 
    2013年5月8日22:56:44
 
  DS18B20 Temperature sensor read data module accomplish;
   (     溫度    傳感器 讀   數(shù)據(jù)  模塊    完成   )
 
  現(xiàn)在還有溫度顯示模塊沒(méi)有完成,硬件是1602液晶屏......
 2013年5月9日19:32:31
   今天,溫度傳感器的程序主體結(jié)構(gòu)全部完成!!!!!
 不容易啊,值得慶祝一下!!!!!!
 一共寫了7天程序!{陸陸續(xù)續(xù)};
 喝個(gè)  品酸乳果汁.......
*/
#include <reg52.h>
typedef unsigned char uint8 ;
typedef unsigned int uint16;

sbit wd = P3^2;  //定義數(shù)據(jù)單總線;
sbit e =P1^5; // 定義1602液晶顯示器數(shù)據(jù)使能端口;
sbit rs=P1^0; // 定義數(shù)據(jù)/指令選擇端口;
sbit rw=P1^1; // 定義  讀/寫  選擇端口;
sbit BF=P0^7; // 定義繁忙位;
bit w=0;  //定義一個(gè)全局一位變量;
 
//===========1602液晶顯示器模塊;===============
busy() //液晶屏繁忙檢測(cè)函數(shù);
{ e=0;
    rs=0;
 rw=0;
   P0=0xff;
  do
  { e=0;   //使能位清零;
    rs=0;   //指令;
 rw=1;   //讀;
 e=1;   //數(shù)據(jù)傳輸啟動(dòng);
  }while(BF); //如果BF==0;則液晶處于空閑狀態(tài);
   e=0;
}
play_data(uint8 wr) //液晶寫入數(shù)據(jù);
{
   busy();   //繁忙檢測(cè);
   P0=wr;   //裝載數(shù)據(jù);
   rs=1;   //數(shù)據(jù);
   rw=0;   //寫入;
   e=1;    //傳輸開(kāi)始;
   e=0;       //傳輸結(jié)束;
}
play_cmd(uint8 cmd)  //液晶寫入指令;
{
  busy(); //繁忙檢測(cè);
  P0=cmd; //裝載數(shù)據(jù);
  rs=0;     //指令;
  rw=0;     //寫入;
  e=1;      //傳輸開(kāi)始;
  e=0;      //傳輸結(jié)束;
}
reset_1602()   //1602液晶顯示器初始化函數(shù);
{
  play_cmd(0x38);
  play_cmd(0x0c);
  play_cmd(0x06);
  play_cmd(0x01);

}

//=========溫度傳感器延時(shí)模塊============================

// sbit led= P1^0;
delay(uint8 num )   //如果unm等于1;延時(shí)16.28微妙;
{
   while(num--);  //如果num大于一,則16.28+(num-1)*6.51.
}
delay2()    //此函數(shù)延時(shí)3.26微秒;
{
   uint8 j=0;
    j=9;
 
 
}

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

reset_1820()  //========復(fù)位溫度傳感器; ========
{
 
  while(wd)
  {
   wd=1;
   delay(140);   //拉高總線,延時(shí)大概921微妙左右;(延時(shí)值自定);
   wd=0;    //總線由單片機(jī)拉低,下為延時(shí)函數(shù),大概800微秒左右;
   delay(61);  //1個(gè)此函數(shù)會(huì)延時(shí)400微妙左右;
   delay(61);  //兩個(gè)是800微妙左右;
   wd=1;    //主機(jī)拉高總線,68微秒左右;
   delay(9);      //延時(shí)68微妙左右
   if(wd==0)      //如果wd是0就終止復(fù)位;(代表復(fù)位成功);
    {
       while(wd==0);   //總線一旦為低,那么就等待從機(jī)再將總線拉高.
    break;    //終止while循環(huán);(reset function end)
    }
   else
     {
     wd=1;
     delay(20);    //延時(shí)140微妙;
  }  
   }
      delay(30); //此時(shí)總線為高電平并延時(shí)205微妙,復(fù)位成功!;
  // if(wd)led=0;//此語(yǔ)句為檢驗(yàn)是否復(fù)位成功;P1^0外接9012三極管接led小燈;
}
 
write_byte(uint8 dat)
{
    uint8 i=0;
   
 for(i=0;i<8;i++)
      {
      wd=0;      //A點(diǎn);
   delay2(); //延時(shí)
      wd=dat & 0x01;
      dat>>=1;
 
   delay(6);  //A點(diǎn)到此處用時(shí)65.11微秒;
   wd=1;   //總線釋放;
   delay2();  //延時(shí)3.26微秒;
   }
 }   //========此函數(shù)執(zhí)行完成之后總線為高電平;

uint8  read_byte() //=====讀8位數(shù)據(jù);===================
{
 uint8 j=0,  dat =0;
 
    for(j=0;j<8;j++)
  {
     dat>>=1;
   wd=0;  // A點(diǎn)  mcu拉低電平3.26微秒;
  delay2();   // 延時(shí)3.26微秒;
  wd=1; 
  if(wd)
   {
     dat|=0x80;
   }      //讀完數(shù)據(jù)后A點(diǎn)到此處是11.93微秒,保持在15微秒之內(nèi);
   delay(9);   // A點(diǎn)到此處80.29微秒; 理想時(shí)間范圍是60--120微秒;
   wd=1;  //釋放總線;
   delay2();  //延時(shí)3.26微秒;
  }
 
   return dat;

}

start_sensor()    //啟動(dòng)傳感器;
{
  reset_1820();
  write_byte(0xcc);  //跳躍命令;
  write_byte(0x44);  //轉(zhuǎn)換temperature(溫度)命令;
}
uint8 read_temp()   //從溫度傳感器度溫度數(shù)據(jù)過(guò)程;
{
  uint8 ak[2];
  uint16  dat=0 , j=0;
    reset_1820();   //復(fù)位溫度傳感器
    write_byte(0xcc);  //跳躍rom命令;
    write_byte(0xbe) ;  // 發(fā)出讀數(shù)據(jù)命令;
    ak[0]=read_byte(); //讀取第一個(gè)字節(jié)數(shù)據(jù);
    ak[1]=read_byte(); //讀取第二個(gè)字節(jié)數(shù)據(jù);
    dat=ak[1];    //要把兩個(gè)八位數(shù)據(jù)載入1個(gè)16位變量里;
    dat<<=8;
    dat|=ak[0];
       j= dat;

  //==========以下是把溫度傳感器內(nèi)部數(shù)據(jù)編譯成16進(jìn)制編碼;
     if((j>>11)==0x1f) //此語(yǔ)句是負(fù)溫度進(jìn)入.0x1f是二進(jìn)制5個(gè)全1;
  {
  dat=(~dat)+1;    //負(fù)溫度要取反加一操作;
  dat/=16;    //傳感器給的溫度系數(shù)要除以16后,得到的數(shù)才是常規(guī)溫度系數(shù);
  w=0;   //此語(yǔ)句是在主函數(shù)中用來(lái)判斷是正溫度還是負(fù)溫度;
  return dat;  //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
  }
     j=dat;
   if((j>>11)==0)   //如果是零則是正溫度;
     {
     dat/=16;    //數(shù)據(jù)直接除以16,就得到了常規(guī)溫度系數(shù);
     w=1;     //1代表正;
     return dat; //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
 
  }
 
   return 130;  //向主函數(shù)返回?cái)?shù)據(jù),并終止函數(shù);
  
}

delay_ms()  //延時(shí)1秒;
{
  uint8 i=250;
  uint16 j=608;
   while(j--)
    { while(i--);
       i=250;
     
    }
 
}
 
error()  //測(cè)溫出錯(cuò);
{
   uint8 i=5, j=0 ,ak[]="Error!";
 
 while(i--)
 {
     play_cmd(0x82);
     while(ak[j]!='\0')
   {
     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--)    //這是啟動(dòng)電源時(shí),液晶顯示:start....(并閃爍3次)
 {   play_cmd(0x82);
    while(num[len]!='\0')
     {
     play_data(num[len++]); 
  }
       len=0;
       delay3();
       play_cmd(0x01);
       delay3();
 }
 
 
 
 while(1)
   {   
     start_sensor();   //啟動(dòng)溫度傳感器;
  delay_ms();    //等待1秒;
  dat = read_temp(); //讀取溫度數(shù)據(jù)并賦給dat變量;
 
   if(dat==130)    //如果返回來(lái)的數(shù)據(jù)是130,表明采集溫度出錯(cuò);
   {
     error();
   }
  else if(w==1)  //如果w是1,就代表正溫度.輸出;
   {
     play_cmd(0x83);
    play_data(dat/10+'0');
    play_data(dat%10+'0');
   }
   else    //否則,就是負(fù)溫度,輸出時(shí)前面加一個(gè)負(fù)號(hào);
     {
    play_cmd(0x82);
    play_data('-');
    play_data(dat/10+'0');
    play_data(dat%10+'0');
  }
 
   } //我的親娘四舅奶奶啊!!!!!!終于完成了!!!!2013年5月9日19:32:10
 
 
   
}

關(guān)閉窗口

相關(guān)文章