STM32驅動DS18B20


DS18B20 是由 DALLAS 半導體公司推出的一種的“一線總線”接口的溫度傳感器。與傳
統的熱敏電阻等測溫元件相比,它是一種新型的體積小、適用電壓寬、與微處理器接口簡單的
數字化溫度傳感器。一線總線結構具有簡潔且經濟的特點,可使用戶輕松地組建傳感器網絡,
從而為測量系統的構建引入全新概念,測量溫度范圍為-55~+125℃  ,精度為±0.5℃。現場溫
度直接以“一線總線”的數字方式傳輸,大大提高了系統的抗干擾性。它能直接讀出被測溫度,
並且可根據實際要求通過簡單的編程實現 9~l2 位的數字值讀數方式。它工作在 3—5. 5 V 的電
壓范圍,采用多種封裝形式,從而使系統設計靈活、方便,設定分辨率及用戶設定的報警溫度

存儲在 EEPROM 中,掉電后依然保存

其內部結構如下所示

DS18B20的通訊方式是單總線的,一般而言,我們遇到的封裝都是如下

其中DQ就是主要的通訊線路,對DS的讀取和寫入都需要主機來控制DQ線路的DQ高低電平的時間來確定,具體如下

一般而言,DQ線需要接一個上拉電阻,所以,才寫操作的最后一步都需要將總線拉高


向DS寫0需要總線拉低至少60US最多120US就算完成,也就是說,1-->0(持續60-120us)-->1 寫入了0

像DS寫入1需要總線拉低最少1us最多15US,然后總線拉高,拉高時間至少15us,一般40us以上即可  1->0(1-15us,推薦5us)-->1(持續15us以上,推薦40us)

由此可見,DS的總線采樣實在總線拉低之后的15us開始的

讀取DS分別為讀取1和讀取0,但是這兩者時序是統一的

首先總線拉低至少1us,最多15us,還是選擇2us,然后釋放總線(也就是說進入輸入模式),等待15us以上的事件,然后采樣,高電平為1低電平為0

1-->0(持續2us,最多15us)-->等待15us以上60us以下-->采樣總線電平,得到1或者0,記得采樣完成之后切換到輸出模式將總線拉高便於下一次使用


DS18B20的命令

DS1820有三個主要數字部件:1)64位激光ROM,2)溫度傳感器,3)非易失性溫度報警觸發器TH和TL



啟動溫度轉換的命令是0X44,讀取命令是0XBE

所以一般而言,對於DS的驅動包含以下幾步

復位-->發 SKIP ROM 命令(0XCC)-->發開始轉換命令(0X44)-->延時-->復
位-->發送 SKIP  ROM 命令(0XCC)-->發讀存儲器命令(0XBE)-->連續讀出兩個字節數據(即
溫度)-->結束

我們在讀取的時候只讀取兩個字節的原因在於DS的存儲器布局

前兩個就是我們需要的溫度,當然也可以讀取全部的,擴展驅動達到其他目的


以下是驅動代碼,STM32驅動代碼中使用了位段操作

#ifndef __Ds18b20H
#define __Ds18b20H 
#include "ioremap.h"   
#include "delay.h"
#include "uart.h"


//IO方向設置
#define Ds18b20IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define Ds18b20IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}



////IO操作函數											   
#define	Ds18b20DQ_OUT PGout(11) //數據端口	PG11 
#define	Ds18b20DQ_IN  PGin(11)  //數據端口	PG11 




u8 Ds18b20Init(void);			//初始化DS18B20


short Ds18b20GetTemp(void);	//獲取溫度


void Ds18b20Start(void);		//開始溫度轉換


void Ds18b20WriteByte(u8 dat);//寫入一個字節


u8 Ds18b20ReadByte(void);		//讀出一個字節


u8 Ds18b20ReadBit(void);		//讀出一個位


u8 Ds18b20Check(void);			//檢測是否存在DS18B20


void Ds18b20Rst(void);			//復位DS18B20   

void Ds18b20Show(void);


#endif















 

#include "ds18b20.h"

//復位DS18B20
void Ds18b20Rst(void)	   
{                 
    Ds18b20IO_OUT(); //SET PA0 OUTPUT
    Ds18b20DQ_OUT=0; //拉低DQ
    DelayUs(750);    //拉低750us
    Ds18b20DQ_OUT=1; //DQ=1 
    DelayUs(15);     //15US
}


//等待DS18B20的回應
//返回1:未檢測到DS18B20的存在
//返回0:存在
u8 Ds18b20Check(void) 	   
{   
    u8 retry=0;
    Ds18b20IO_IN();//SET PA0 INPUT	 
    while (Ds18b20DQ_IN&&retry<200)
    {
        retry++;
        DelayUs(1);
    };	 
    if(retry>=200)return 1;
    else retry=0;
    while (!Ds18b20DQ_IN&&retry<240)
    {
        retry++;
        DelayUs(1);
    };
    if(retry>=240)return 1;	    
    return 0;
}


//從DS18B20讀取一個位
//返回值:1/0
u8 Ds18b20ReadBit(void) 			 // read one bit
{
    u8 data;
    Ds18b20IO_OUT();//SET PA0 OUTPUT
    Ds18b20DQ_OUT=0; 
    DelayUs(2);
    Ds18b20DQ_OUT=1; 
    Ds18b20IO_IN();//SET PA0 INPUT
    DelayUs(12);
    if(Ds18b20DQ_IN)data=1;
    else data=0;	 
    DelayUs(50);           
    return data;
}


//從DS18B20讀取一個字節
//返回值:讀到的數據
u8 Ds18b20ReadByte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
    for (i=1;i<=8;i++) 
    {
        j=Ds18b20ReadBit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}


//寫一個字節到DS18B20
//dat:要寫入的字節
void Ds18b20WriteByte(u8 dat)     
{             
    u8 j;
    u8 testb;
    Ds18b20IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
    {
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            Ds18b20DQ_OUT=0;// Write 1
            DelayUs(2);                            
            Ds18b20DQ_OUT=1;
            DelayUs(60);             
        }
        else 
        {
            Ds18b20DQ_OUT=0;// Write 0
            DelayUs(60);             
            Ds18b20DQ_OUT=1;
            DelayUs(2);                          
        }
    }
}


//開始溫度轉換
void Ds18b20Start(void)// ds1820 start convert
{   						               
    Ds18b20Rst();	   
    Ds18b20Check();	 
    Ds18b20WriteByte(0xcc);// skip rom
    Ds18b20WriteByte(0x44);// convert
} 


//初始化DS18B20的IO口 DQ 同時檢測DS的存在
//返回1:不存在
//返回0:存在    	 
u8 Ds18b20Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PORTG口時鍾 
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//PORTG.11 推挽輸出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    
    GPIO_SetBits(GPIOG,GPIO_Pin_11);    //輸出1
    
    Ds18b20Rst();
    
    return Ds18b20Check();
}  


//從ds18b20得到溫度值
//精度:0.1C
//返回值:溫度值 (-550~1250) 
short Ds18b20GetTemp(void)
{
    u8 temp;
    u8 TL,TH;
    short tem;
    Ds18b20Start ();                    // ds1820 start convert
    Ds18b20Rst();
    Ds18b20Check();	 
    Ds18b20WriteByte(0xcc);// skip rom
    Ds18b20WriteByte(0xbe);// convert	    
    TL=Ds18b20ReadByte(); // LSB   
    TH=Ds18b20ReadByte(); // MSB  
    
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//溫度為負  
    }else temp=1;//溫度為正	  	  
    tem=TH; //獲得高八位
    tem<<=8;    
    tem+=TL;//獲得底八位
    tem=(short)((float)tem*0.625);//轉換     
    if(temp)return tem; //返回溫度值
    else return -tem;    
} 

void Ds18b20Show(void)
{
	short t = 0;
	t = Ds18b20GetTemp();
	printf("ds18b20 temp is %d\r\n",t);
}




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM