DS18B20 測溫程序徹底解讀

 硬件51板
    (1)單線ds18b20接 P2.2
    (2)使用外部電源給ds18b20供電,沒有使用寄生電源奧
軟件
     Kei uVision 2
    剛開始對時序把握很差,但是在論壇裏沒找到比較詳細的解釋,因此俺倒塌了這個東東,就把俺的經驗貼上來,供你們參考,呵呵…… 
    若有錯誤請指正

#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit ds=P2^2;
sbit dula=P2^6;
sbit wela=P2^7;
uchar flag ;
uint temp;               //參數temp必定要聲明爲 int 型 
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};     //不帶小數點數字編碼

uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};        //帶小數點數字編碼

/*延時函數*/
void TempDelay (uchar us)
{
   while(us--);
}

void delay(uint count) //延時子函數
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}

/*串口初始化,波特率9600,方式1 */
void init_com()
{
   TMOD=0x20;      //設置定時器1爲模式2
   TH1=0xfd;       //裝初值設定波特率
   TL1=0xfd;
   TR1=1;          //啓動定時器
   SM0=0;          //串口通訊模式設置
   SM1=1;
// REN=1;          //串口容許接收數據
   PCON=0;         //波特率不倍頻
 //  SMOD=0;       //波特率不倍頻
  // EA=1;          //開總中斷
  //ES=1;          //開串行中斷
}

/*數碼管的顯示 */
void display(uint temp)
{
    uchar bai,shi,ge;
    bai=temp/100;
    shi=temp%100/10;
    ge=temp%100%10;

dula=0;
    P0=table[bai];  //顯示百位
dula=1;         //從0到1,有個上升沿,解除鎖存,顯示相應段 
dula=0;         //從1到0再次鎖存
          
    wela=0;
    P0=0xfe;
wela=1;
wela=0;
delay(1);    //延時約2ms

P0=table1[shi];  //顯示十位
dula=1;
    dula=0;
    
P0=0xfd;
wela=1;
    wela=0;
    delay(1);

    P0=table[ge];  //顯示個位
dula=1;
    dula=0;
    
P0=0xfb;
wela=1;
    wela=0;
    delay(1);
}
/***************************************** 
時序:初始化時序、讀時序、寫時序。
全部時序都是將主機(單片機)做爲主設備,單總
線器件做爲從設備。而每一次命令和數據的傳輸
都是從主機主動啓動寫時序開始,若是要求單總
線器件回送數據,在進行寫命令後,主機需啓動
讀時序完成數據接收。數據和命令的傳輸都是低
位在先。  
初始化時序:復位脈衝 存在脈衝
        讀;1 或 0時序
        寫;1 或 0時序
只有存在脈衝信號是從18b20(從機)發出的,其
它信號都是由主機發出的。
存在脈衝:讓主機(總線)知道從機(18b20)已
經作好了準備。
******************************************/


/*--------------------------------------------------------------------------------------------------------------------
初始化:檢測總線控制器發出的復位脈衝
和ds18b20的任何通信都要從初始化開始

初始化序列包括一個由總線控制器發出的復位脈衝
和跟在其後由從機發出的存在脈衝。

初始化:復位脈衝+存在脈衝

具體操做:
  總線控制器發出(TX)一個復位脈衝 (一個最少保持480μs 的低電平信號),而後釋放總線,
進入接收狀態(RX)。單線總線由5K 上拉電阻拉到高電平。探測到I/O 引腳上的上升沿後
DS1820 等待15~60μs,而後發出存在脈衝(一個60~240μs 的低電平信號)。

  具體看"倒塌 18b20"文檔裏的 " 單線復位脈衝時序和1-wire presence detect "的時序圖
-------------------------------------------------------------------------------------------------------------------*/
void ds_reset(void)
{
   ds=1;
   _nop_();        //1us
   ds=0;
   TempDelay(80);  //當總線停留在低電平超過480us,總線上因此器件都將被複位,這裏//延時約530us總線停留在低電平超過480μs,總線上的全部器件都
 //將被複位。
   _nop_(); 
   ds=1;           //產生復位脈衝後,微處理器釋放總線,讓總線處於空閒狀態,緣由查//18b20中文資料

   TempDelay(5);  //釋放總線後,以便從機18b20經過拉低總線來指示其是否在線,
                  //存在檢測高電平時間:15~60us, 因此延時44us,進行            1-wire presence //detect(單線存在檢測)
   _nop_();
   _nop_();
   _nop_();
   if(ds==0)
        flag=1;       //detect 18b20 success
   else
        flag=0;       //detect 18b20 fail
  TempDelay(20);    //存在檢測低電平時間:60~240us,因此延時約140us
   _nop_();
   _nop_();
   ds=1;          //再次拉高總線,讓總線處於空閒狀態
/**/
}

/*----------------------------------------
讀/寫時間隙:
DS1820 的數據讀寫是經過時間隙處理
位和命令字來確認信息交換。
------------------------------------------*/
bit  ds_read_bit(void)    //讀一位
{
   bit dat;
   ds=0;         //單片機(微處理器)將總線拉低
  _nop_();       //讀時隙起始於微處理器將總線拉低至少1us
   ds=1;        //拉低總線後接着釋放總線,讓從機18b20可以接管總線,輸出有效數據
   _nop_();
   _nop_();          //小延時一下,讀取18b20上的數據 ,由於從ds18b20上輸出的數據
//在讀"時間隙"降低沿出現15us內有效
   dat=ds;           //主機讀從機18b20輸出的數據,這些數據在讀時隙的降低沿出現//15us內有效 
   TempDelay(10);    //全部讀"時間隙"必須60~120us,這裏77us
   return(dat);       //返回有效數據
}
uchar ds_read_byte(void ) //讀一字節
{

uchar value,i,j;
value=0;           //必定別忘了給初值
for(i=0;i<8;i++)
{
    j=ds_read_bit();
     value=(j<<7)|(value>>1);   //這一步的說明在一個word文檔裏面
}
return(value);        //返回一個字節的數據
}
void ds_write_byte(uchar dat) //寫一個字節
{
  uchar i;
  bit onebit;        //必定不要忘了,onebit是一位
  for(i=1;i<=8;i++) 
  {
    onebit=dat&0x01;
    dat=dat>>1;
if(onebit)      //寫 1
{
ds=0;
_nop_();    
      _nop_();      //看時序圖,至少延時1us,才產生寫"時間隙"  
ds=1;       //寫時間隙開始後的15μs內容許數據線拉到高電平
     TempDelay(5);  //全部寫時間隙必須最少持續60us
}
else         //寫 0
{
ds=0;
     TempDelay(8);    //主機要生成一個寫0 時間隙,必須把數據線拉到低電平並保持至少60μs,這裏64us
ds=1;
_nop_();
     _nop_();
}
  }
}

/***************************************** 
主機(單片機)控制18B20完成溫度轉換要通過三個步驟:
每一次讀寫以前都要18B20進行復位操做,復位成功後發送
一條ROM指令,最後發送RAM指令,這樣才能對DS18b20進行
 預約的操做。
 復位要求主CPU將數據線下拉500us,而後釋放,當ds18B20
 受到信號後等待16~60us,後發出60~240us的存在低脈衝,
 主CPU收到此信號表示復位成功
******************************************/ 

/*----------------------------------------
進行溫度轉換:
先初始化
而後跳過ROM:跳過64位ROM地址,直接向ds18B20發溫度轉換命令,適合單片工做
發送溫度轉換命令
------------------------------------------*/

void tem_change()
{
  ds_reset(); 
  delay(1);              //約2ms
  ds_write_byte(0xcc);
  ds_write_byte(0x44);
}

/*----------------------------------------
得到溫度:
------------------------------------------*/
uint get_temperature()
{
  float wendu;
  uchar a,b;
  ds_reset();
  delay(1);              //約2ms
  ds_write_byte(0xcc);
  ds_write_byte(0xbe);
  a=ds_read_byte();
  b=ds_read_byte();
  temp=b;
  temp<<=8;
  temp=temp|a;
  wendu=temp*0.0625;     //溫度讀取的解釋我記錄在 "倒塌 18B20"裏面
  temp=wendu*10+0.5;
  return temp;
}
/*----------------------------------------
讀ROM   
------------------------------------------*/
/*
void ds_read_rom()                  //這裏沒有用到
{
   uchar a,b;
   ds_reset();
   delay(30);
   ds_write_byte(0x33);
   a=ds_read_byte();
   b=ds_read_byte();
}
*/
void main()
{
   uint a;
   init_com();
   while(1)
   {
tem_change();          //12位轉換時間最大爲750ms
for(a=10;a>0;a--)
{
display( get_temperature());
}
   }
}
 php

相關文章
相關標籤/搜索