新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 DS18B20代碼詳解

        STM32 DS18B20代碼詳解

        作者: 時間:2016-11-13 來源:網絡 收藏
        DS18B20是最常用來學習某一個新的開發工具的,程序都是大同小異,主要是要注意時序中的延時要準確,指令要正確,這里記錄一下!

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

        ------------------第一部分是--------ds18b20.h----------------------

        #ifndef __DS18B20_H
        #define __DS18B20_H

        #include "stm32f10x.h"
        #include "bsp_SysTick.h" //精確延時函數頭文件----參考http://blog.csdn.net/xuxuechen/article/details/40783209這個看一下

        #define HIGH 1
        #define LOW 0

        #define DS18B20_CLK RCC_APB2Periph_GPIOB
        #define DS18B20_PIN GPIO_Pin_10
        #define DS18B20_PORT GPIOB //總體代表DS18B20的GPIO口為PB10

        //帶參宏,可以像內聯函數一樣使用,輸出高電平或低電平
        #define DS18B20_DATA_OUT(a)if (a)
        GPIO_SetBits(GPIOB,GPIO_Pin_10);
        else
        GPIO_ResetBits(GPIOB,GPIO_Pin_10)
        //讀取引腳的電平
        #define DS18B20_DATA_IN() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)

        uint8_t DS18B20_Init(void);
        float DS18B20_Get_Temp(uint8_t *a,uint8_t b);
        void read_serial(uint8_t *serial);
        #endif /* __DS18B20_H */

        ----------------第二部分是----------DS18B20.C源文件---------------------

        #include "bsp_ds18b20.h"

        uint8_t serial_1[8]={0x28,0x2d,0x9a,0xdd,0x02,0x00,0x00,0x3b};
        uint8_t serial_2[8]={0x28,0x3b,0x2b,0xbc,0x02,0x00,0x00,0x4f};
        uint8_t serial_3[8]={0x28,0x00,0x49,0x1b,0x03,0x00,0x00,0x4c};//序列號,需要根據自己的DS18B20修改,具體讀取方法,會有另一篇介紹。

        static void DS18B20_GPIO_Config(void)
        {
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE);
        GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);

        GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
        }

        static void DS18B20_Mode_IPU(void) //使DS18B20-DATA引腳變為輸入模式
        {
        GPIO_InitTypeDef GPIO_InitStructure;

        GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
        }

        static void DS18B20_Mode_Out_PP(void) //使DS18B20-DATA引腳變為輸出模式
        {
        GPIO_InitTypeDef GPIO_InitStructure;

        GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
        }

        static void DS18B20_Rst(void) //主機給從機發送復位脈沖
        {
        DS18B20_Mode_Out_PP();
        DS18B20_DATA_OUT(LOW);
        Delay_Us(750); //主機至少產生480us的低電平復位信號
        DS18B20_DATA_OUT(HIGH); //主機在產生復位信號后,需將總線拉高
        Delay_Us(15); //從機接收到主機的復位信號后,會在15~60us后給主機發一個存在脈沖
        }

        static uint8_t DS18B20_Presence(void) //檢測從機給主機返回的存在脈沖
        {
        uint8_t pulse_time = 0;

        DS18B20_Mode_IPU(); //主機設置為上拉輸入

        //等待存在脈沖的到來,存在脈沖為一個60~240us的低電平信號
        //如果存在脈沖沒有來則做超時處理,從機接收到主機的復位信號后,會在15~60us后給主機發一個存在脈沖

        while( DS18B20_DATA_IN() && pulse_time<100 )
        {
        pulse_time++;
        Delay_Us(1);
        }
        if( pulse_time >=100 ) //經過100us后,存在脈沖都還沒有到來
        return 1;
        else
        pulse_time = 0;
        while( !DS18B20_DATA_IN() && pulse_time<240 ) //存在脈沖到來,且存在的時間不能超過240us
        {
        pulse_time++;
        Delay_Us(1);
        }
        if( pulse_time >=240 )
        return 1;
        else
        return 0;
        }

        static uint8_t DS18B20_Read_Bit(void) //從DS18B20讀取一個bit
        {
        uint8_t dat;

        DS18B20_Mode_Out_PP(); //讀0和讀1的時間至少要大于60us
        DS18B20_DATA_OUT(LOW); //讀時間的起始:必須由主機產生 >1us <15us 的低電平信號
        Delay_Us(10);
        DS18B20_Mode_IPU(); //設置成輸入,釋放總線,由外部上拉電阻將總線拉高
        if( DS18B20_DATA_IN() == SET )
        dat = 1;
        else
        dat = 0;
        Delay_Us(45); //這個延時參數請參考時序圖

        return dat;
        }

        uint8_t DS18B20_Read_Byte(void) //從DS18B20讀一個字節,低位先行
        {
        uint8_t i, j, dat = 0;

        for(i=0; i<8; i++)
        {
        j = DS18B20_Read_Bit();
        dat = (dat) | (j< }

        return dat;
        }

        void DS18B20_Write_Byte(uint8_t dat) //寫一個字節到DS18B20,低位先行
        {
        uint8_t i, testb;

        DS18B20_Mode_Out_PP();
        for( i=0; i<8; i++ )
        {
        testb = dat&0x01;
        dat = dat>>1;
        if (testb)//寫0和寫1的時間至少要大于60us
        {
        DS18B20_DATA_OUT(LOW);
        Delay_Us(8);
        DS18B20_DATA_OUT(HIGH);
        Delay_Us(58);
        }
        else
        {
        DS18B20_DATA_OUT(LOW);
        Delay_Us(70);
        DS18B20_DATA_OUT(HIGH);
        Delay_Us(2);
        }
        }
        }

        void DS18B20_Start(void)
        {
        DS18B20_Rst();
        DS18B20_Presence();
        DS18B20_Write_Byte(0XCC); //跳過 ROM
        DS18B20_Write_Byte(0X44); //開始轉換
        }

        uint8_t DS18B20_Init(void)
        {
        DS18B20_GPIO_Config();
        DS18B20_Rst();

        return DS18B20_Presence();
        }

        void DS18B20_Match_Serial(uint8_t a) //匹配序列號
        {
        uint8_t i;
        DS18B20_Rst();
        DS18B20_Presence();
        DS18B20_Write_Byte(0X55); //匹配序列號指令
        if(a==1)
        {
        for(i=0;i<8;i++)
        DS18B20_Write_Byte(serial_1[i]);
        }
        else if(a==2)
        {
        for(i=0;i<8;i++)
        DS18B20_Write_Byte(serial_2[i]);
        }
        else if(a==3)
        {
        for(i=0;i<8;i++)
        DS18B20_Write_Byte(serial_3[i]);
        }
        }


        //存儲的溫度是16 位的帶符號擴展的二進制補碼形式
        //當工作在12位分辨率時,其中5個符號位,7個整數位,4個小數位

        // |---------整數----------|-----小數 分辨率 1/(2^4)=0.0625----|
        //低字節 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |

        // |-----符號位:0->正 1->負-------|-----------整數-----------|
        //高字節 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |
        //溫度 = 符號位 + 整數 + 小數*0.0625

        float DS18B20_Get_Temp(uint8_t*a,uint16_tgo_temp,uint8_tb)
        {
        uint8_t tpmsb, tplsb;
        short s_tem;
        float f_tem;
        int temp_num;

        DS18B20_Rst();
        DS18B20_Presence();
        DS18B20_Write_Byte(0XCC); // 跳過 ROM
        DS18B20_Match_Serial(b); //匹配序列號
        DS18B20_Write_Byte(0X44); // 開始轉換

        DS18B20_Rst();
        DS18B20_Presence();
        DS18B20_Write_Byte(0XCC); //跳過 ROM
        DS18B20_Match_Serial(b); //匹配序列號
        DS18B20_Write_Byte(0XBE); //讀溫度值

        tplsb = DS18B20_Read_Byte();
        tpmsb = DS18B20_Read_Byte();

        s_tem = tpmsb<<8;
        s_tem = s_tem | tplsb;

        if( s_tem < 0 ) //負溫度
        {
        f_tem = (~s_tem+1) * 0.0625;
        temp_num = (~s_tem+1) * 0.0625*10;
        go_temp= temp_num;
        if(temp_num>=1000)
        {
        a[0]=-;
        a[1]= temp_num/1000+0;
        a[2]= temp_num%1000/100+0;
        a[3]= temp_num%100/10+0;
        a[4]=.;
        a[5]= temp_num%10+0;
        a[6]=

        主站蜘蛛池模板: 大悟县| 通渭县| 江门市| 长治市| 福安市| 平昌县| 乌鲁木齐县| 阿克陶县| 陈巴尔虎旗| 余江县| 祁东县| 平和县| 石阡县| 三亚市| 岳池县| 濉溪县| 永济市| 桃园县| 道孚县| 鱼台县| 云和县| 古浪县| 富民县| 浑源县| 沙湾县| 旌德县| 疏附县| 仪征市| 仲巴县| 兰西县| 曲松县| 深州市| 周口市| 天等县| 台中县| 合水县| 花莲市| 灵武市| 镇巴县| 临高县| 乐至县|