51單片機-溫度傳感器DS18B20

發(fā)布時(shí)間:2011-3-22 11:37    發(fā)布者:techshare
關(guān)鍵詞: 51單片機 , DS18B20 , 溫度傳感器
溫度傳感器是各種傳感器中最常用的一種,早期使用的是模擬溫度傳感器,如熱敏電阻,隨著(zhù)環(huán)境溫度的變化,它的阻值也發(fā)生線(xiàn)性變化,用處理器采集電阻兩端的電壓,然后根據某個(gè)公式就可以計算出當前環(huán)境溫度。美國DALLAS半導體公司推出的數字化溫度傳感器DS18B20采用單總線(xiàn)協(xié)議,即與單片機接口僅需占用一個(gè)I/O端口,無(wú)需任何外部元件,直接將環(huán)境溫度轉化成數字信號,以數字碼方式串行輸出,從而大大簡(jiǎn)化了傳感器與處理器的接口。  

DS18B20的三種封裝:  


   
DS18B20的內部結構:  


   
它采用單條信號線(xiàn),既可傳輸時(shí)鐘,又可傳輸數據,而且數據傳輸是雙向的。如果要控制多個(gè)DS18B20進(jìn)行溫度采集,只要將所有的DS18B20的I/O口全部連接到一起就可以了。在具體操作時(shí),通過(guò)讀取每個(gè)DS18B20內部芯片的序列號來(lái)識別。64位光刻ROM中的序列號是出場(chǎng)前被光刻好的,他可以看做該DS18B20的地址序列碼。  

DS18B20的復位時(shí)序:  


   
DS18B20復位,確定其存在:     #include <reg52.h>
#define uint unsigned int
uint i;
sbit DQ = P3^3;
sbit bell = P3^4;

void reset(){
        DQ = 1;                //開(kāi)始的時(shí)候是高脈沖
        DQ=0;                      //然后是低脈沖
        i=103;
          while(i>0)i--;        //低脈沖需要延遲一會(huì )兒
          DQ=1;                        //數據線(xiàn)拉高,系統將總線(xiàn)放開(kāi),并進(jìn)入接受狀態(tài)
          i=4;
          while(i>0)i--;        //延時(shí)等待,若初始化成功則在15"60ms內產(chǎn)生一個(gè)由
        if(DQ == 0){        //DS18B20在檢測到總線(xiàn)的上升沿后,等待15"60ms,接著(zhù)
                while(DQ == 0); //在T2時(shí)刻發(fā)出存在脈沖(低電平)
                bell = 0;
        }
        else
                bell = 1;        
}

void main(){
        reset();
        while(1);
}






   



DS18B20的寫(xiě)0和寫(xiě)1時(shí)序:







DS18B20的讀數據時(shí)序:










讀出光刻ROM中的ID號,在LCD上顯示:


  
    #include <reg52.h>
#include<intrins.h>
sbit DQ = P3^3;
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;
sbit bell = P3^4;

#define uchar unsigned char
#define uint unsigned int
#define        nop() _nop_()

uint i;
uchar value;
uchar DS[8];
uchar Time_Data[]={'0','1','2','3','4','5','6','7',
                                   '8','9','A','B','C','D','E','F'};

void delay(uchar t){
   while(--t);
}

void lcd_com(uchar s){
    RS = 0;                    //低電平,寫(xiě)指令
    P2 = s;                    //傳數據
    delay(14);                //看時(shí)序圖,數據需要穩定一段時(shí)間
    E = 1;                            //給一個(gè)高脈沖,發(fā)送命令
    delay(14);                    //如圖,高脈沖延時(shí)一段時(shí)間,確保命令發(fā)送
    E = 0;                            //發(fā)送結束E置為低電平
}

void lcd_data(uchar s){
    RS = 1;
    P2 = s;
    delay(14);
    E = 1;
    delay(14);
    E = 0;
}

void init_lcd(){
    RS = 1;         //先發(fā)指令,在初始時(shí)刻RS是高,E和RW是低
    E = 0;
    RW = 0;
    lcd_com(0x38);           //設置為16*2顯示,5*7點(diǎn)陣,8位數據接口
    lcd_com(0x0f);           //開(kāi)顯示,顯示光標,光標閃爍
    lcd_com(0x06);           //讀寫(xiě)一個(gè)字符后地址指針加一
    lcd_com(0x01);
}

void Display_lcd(uchar y, uchar x, uchar value){
        if(y)
                lcd_com(0x80+0x40+x);   //如果y為1,寫(xiě)在第二行
        else
                lcd_com(0x80+x);
        lcd_data(value);                        //寫(xiě)到LCD602上
}
         
void DS18B20_reset(){
        DQ = 1;                //開(kāi)始的時(shí)候是高脈沖
        DQ=0;                //然后是低脈沖
        i=103;
          while(i>0)i--;        //低脈沖需要延遲一會(huì )兒
          DQ=1;                        //數據線(xiàn)拉高
          i=4;
          while(i>0)i--;        //延時(shí)等待,若初始化成功則在15"60ms內產(chǎn)生一個(gè)由
        if(DQ == 0){        //DS18B20返回的低電平
                while(DQ == 0);
        //        bell = 0;
        }
        else
                bell = 1;        
}

uchar DS18B20_read(void)
{
        uchar i = 0;
        uchar Value = 0;
        for(i = 0; i < 8; i ++)
                {
                        DQ = 1;         
                        DQ = 0;
                        delay(1);   
                        DQ = 1;      //在T1時(shí)刻將總線(xiàn)拉高,產(chǎn)生讀時(shí)間隙
                        delay(1);    //讀時(shí)隙在T1和T2之間有效
                        if(DQ)
                                {
                                        Value |= 0x01 << i;
                                }
                        delay(17);   //必須在T3時(shí)刻之間主機完成讀操作
                        DQ = 1;
                        nop();
                }
        return Value;
}
        
void DS18B20_write(uchar Value){
        for(i = 0; i < 8; i++){
                DQ = 1;              
                DQ = 0;              //當t0從高拉低產(chǎn)生寫(xiě)時(shí)隙,
                delay(5);        
                DQ = Value & 0x01;   //必須在t0開(kāi)始的15us內將數據送到總線(xiàn)上
                delay(20);           //DS18B20在t0后的15us"60us內對總線(xiàn)采樣
                DQ = 1;              //如果采到低電平則寫(xiě)入0,高電平寫(xiě)入1
                Value >>= 1;
                delay(2);
        }        
}
  
void DS18B20_ID_read(){
        DS18B20_reset();
        DS18B20_write(0x33);
        for(i = 0; i < 8; i++)
                DS[ i] = DS18B20_read();
}

void main(){
         init_lcd();
         while(1){
                 DS18B20_ID_read();
                 Display_lcd(0,0,'>');
                Display_lcd(0,1,':');
                Display_lcd(0,2,Time_Data[DS[0]/16]);
                Display_lcd(0,3,Time_Data[DS[0]%16]);
                Display_lcd(0,4,'>');
                Display_lcd(0,5,':');
                Display_lcd(0,6,Time_Data[DS[1]/16]);
                Display_lcd(0,7,Time_Data[DS[1]%16]);
                Display_lcd(0,8,'>');
                Display_lcd(0,9,':');
                Display_lcd(0,10,Time_Data[DS[2]/16]);
                Display_lcd(0,11,Time_Data[DS[2]%16]);
                Display_lcd(0,12,'>');
                Display_lcd(0,13,':');
                Display_lcd(0,14,Time_Data[DS[3]/16]);
                Display_lcd(0,15,Time_Data[DS[3]%16]);
                Display_lcd(1,0,'>');
                Display_lcd(1,1,':');
                Display_lcd(1,2,Time_Data[DS[4]/16]);
                Display_lcd(1,3,Time_Data[DS[4]%16]);
                Display_lcd(1,4,'>');
                Display_lcd(1,5,':');
                Display_lcd(1,6,Time_Data[DS[5]/16]);
                Display_lcd(1,7,Time_Data[DS[5]%16]);
                Display_lcd(1,8,'>');
                Display_lcd(1,9,':');
                Display_lcd(1,10,Time_Data[DS[6]/16]);
                Display_lcd(1,11,Time_Data[DS[6]%16]);
                Display_lcd(1,12,'>');
                Display_lcd(1,13,':');
                Display_lcd(1,14,Time_Data[DS[7]/16]);
                Display_lcd(1,15,Time_Data[DS[7]%16]);
         }
}
  

  


  單只DS18B20工作流程:

  



  2只DS18B20并聯(lián)工作流程:

  



  DS18B20溫度存儲格式:

  



  DS18B20暫存器的分布:

  



  DS18B20內部ROM指令:

  



  DS18B20內部RAM指令:

  

  

讀出當前溫度,在LCD上顯示,溫度超過(guò)一定時(shí),報警。
  



  #include <reg52.h>
#include<intrins.h>
sbit DQ = P3^3;
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;
sbit bell = P3^4;

#define uchar unsigned char
#define uint unsigned int
#define        nop() _nop_()

uint i;
uchar value;
uchar DS[8];
uchar Time_Data[]={'0','1','2','3','4','5','6','7',
                                   '8','9','A','B','C','D','E','F'};

void delay(uchar t){
   while(--t);
}

void Lcd_Com(uchar s){
    RS = 0;                    //低電平,寫(xiě)指令
    P2 = s;                    //傳數據
    delay(14);                //看時(shí)序圖,數據需要穩定一段時(shí)間
    E = 1;                            //給一個(gè)高脈沖,發(fā)送命令
    delay(14);                    //如圖,高脈沖延時(shí)一段時(shí)間,確保命令發(fā)送
    E = 0;                            //發(fā)送結束E置為低電平
}

void Lcd_Data(uchar s){
    RS = 1;
    P2 = s;
    delay(14);
    E = 1;
    delay(14);
    E = 0;
}

void Init_Lcd(){
    RS = 1;         //先發(fā)指令,在初始時(shí)刻RS是高,E和RW是低
    E = 0;
    RW = 0;
    Lcd_Com(0x38);           //設置為16*2顯示,5*7點(diǎn)陣,8位數據接口
    Lcd_Com(0x0f);           //開(kāi)顯示,顯示光標,光標閃爍
    Lcd_Com(0x06);           //讀寫(xiě)一個(gè)字符后地址指針加一
    Lcd_Com(0x01);
}

void Display_Lcd(uchar y, uchar x, uchar value){
        if(y)
                Lcd_Com(0x80+0x40+x);   //如果y為1,寫(xiě)在第二行
        else
                Lcd_Com(0x80+x);
        Lcd_Data(value);                        //寫(xiě)到LCD602上
}
         
void DS18B20_Reset(){
        DQ = 1;                //開(kāi)始的時(shí)候是高脈沖
        DQ=0;                //然后是低脈沖
        i=103;
          while(i>0)i--;        //低脈沖需要延遲一會(huì )兒
          DQ=1;                        //數據線(xiàn)拉高
          i=4;
          while(i>0)i--;        //延時(shí)等待,若初始化成功則在15"60ms內產(chǎn)生一個(gè)由
        if(DQ == 0){        //DS18B20返回的低電平
                while(DQ == 0);
        //        bell = 0;
        }
        else
                bell = 1;        
}

uchar DS18B20_Read(void)
{
        uchar i = 0;
        uchar Value = 0;
        for(i = 0; i < 8; i ++)
                {
                        DQ = 1;
                        DQ = 0;
                        delay(1);
                        DQ = 1;
                        delay(1);
                        if(DQ)
                                {
                                        Value |= 0x01 << i;
                                }
                        delay(17);
                        DQ = 1;
                        nop();
                }
        return Value;
}
        
void DS18B20_Write(uchar Value){
        for(i = 0; i < 8; i++){
                DQ = 1;
                DQ = 0;
                delay(5);
                DQ = Value & 0x01;
                delay(20);
                DQ = 1;
                Value >>= 1;
                delay(2);
        }        
}
  
uchar DS18B20_Temp_Read(){
        uchar temp_h,temp_l,temp;
        DS18B20_Reset();                        //復位
        DS18B20_Write(0x0cc);                //跳過(guò)ROM,只有一個(gè)所以跳過(guò)
        DS18B20_Write(0x44);                //開(kāi)始溫度轉換
        DS18B20_Reset();                        //復位
        DS18B20_Write(0x0cc);                //跳過(guò)ROM
        DS18B20_Write(0x0be);                //讀暫存器
        temp_l = DS18B20_Read();        //讀出溫度低8位
        temp_h = DS18B20_Read();        //讀出溫度高8位
        temp_l >>= 4;                                //去掉4位小數位
        temp_h <<= 4;                                //去掉4位符號位
        temp = temp_h | temp_l;               
        temp = temp & 0x7f;                        //最高位是符號位
        return temp;        
}

void main(){
         uchar temp;
         Init_Lcd();
         while(1){
                 temp = DS18B20_Temp_Read();
                if(temp > 25)                                 //如果溫度大于25報警
                        bell = 0;
                else
                        bell = 1;
                Display_Lcd(0,0,'T');
                Display_Lcd(0,1,'E');
                Display_Lcd(0,2,'M');
                Display_Lcd(0,3,'P');
                Display_Lcd(0,4,':');
                Display_Lcd(0,5,Time_Data[temp/100]);
                Display_Lcd(0,6,Time_Data[temp%100/10]);
                Display_Lcd(0,7,Time_Data[temp%10]);
         }
}

李萬(wàn)鵬
本文地址:http://selenalain.com/thread-59318-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
williamkmcn 發(fā)表于 2011-7-7 16:58:43
好東西值得收藏
williamkmcn 發(fā)表于 2011-7-7 16:59:00
好東西值得收藏
horse 發(fā)表于 2017-1-24 10:41:35
收藏學(xué)習了!
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页