新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機中使用DS18B20溫度傳感器C語言程序(參考1)

        單片機中使用DS18B20溫度傳感器C語言程序(參考1)

        作者: 時間:2016-11-18 來源:網絡 收藏
        單片機中使用DS18B20溫度傳感器C語言程序(參考1)

        /********************************************************************************
        DS18B20 測溫程序

        本文引用地址:http://www.104case.com/article/201611/315667.htm

        硬件:AT89S52
        (1)單線ds18b20接 P2.2
        (2)七段數碼管接P0口
        (3)使用外部電源給ds18b20供電,沒有使用寄生電源
        軟件:Kei uVision 3

        **********************************************************************************/
        #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; //得到真實十進制溫度值,因為DS18B20
        //可以精確到0.0625度,所以讀回數據的最低位代表的是 //0.0625度

        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());
        }
        }
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 万荣县| 中西区| 轮台县| 惠来县| 灵璧县| 陕西省| 巴彦淖尔市| 富平县| 鄄城县| 巴青县| 静海县| 肇州县| 繁昌县| 临漳县| 阳曲县| 囊谦县| 革吉县| 平度市| 海安县| 康乐县| 璧山县| 菏泽市| 定襄县| 通海县| 黄浦区| 定西市| 云安县| 清原| 永定县| 那曲县| 乌拉特中旗| 堆龙德庆县| 虎林市| 雅安市| 莫力| 出国| 金山区| 宁城县| 启东市| 锡林浩特市| 巫溪县|