DS18B20讀取溫度,序號匹配


 1 /*  DS18B20時鍾端口、引腳定義 */
 2 #define DS18B20            GPIOC              
 3 #define DS18B20_Onboard    (GPIO_Pin_15)
 4 #define DS18B20_PORT_RCC   RCC_APB2Periph_GPIOC
 5 #define ds_count 20
 6 
 7 ///IO操作函數                                               
 8 #define DS18B20_DQ_OUT     PCout(15)
 9 #define DS18B20_DQ_IN      PCin(15)
10 
11 #define dsmax              6  //最多允許溫度傳感器的數量

配置DS18B20初始化函數,輸入配置,輸出配置,參考DS18B20數據手冊:

 1 void DS18B20_Reset(void)
 2 {
 3     DS18B20_IO_OUT(); //SET PC15 OUTPUT
 4     DS18B20_DQ_OUT=0; //拉低DQ
 5     delay_us(750);    //拉低750us
 6     DS18B20_DQ_OUT=1; //DQ=1
 7     delay_us(35);     //35US
 8 }
 9 
10 u8 DS18B20_Check(void)
11 {
12     u8 retry=0;
13     DS18B20_IO_IN();//SET PC15 INPUT
14     while(DS18B20_DQ_IN&&retry<200)
15     {
16         retry++;
17         delay_us(1);
18     };
19     if(retry>=200) return 1;
20     else retry = 0;
21     while (!DS18B20_DQ_IN && retry <240)
22     {
23         retry++;
24         delay_us(1);
25     };
26     if(retry>=240) return 1;
27     return 0;
28 }
29 
30 u8 DS18B20_Init(void)
31 {
32     GPIO_InitTypeDef  GPIO_InitStructure;
33     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE );
34     PWR_BackupAccessCmd( ENABLE );/* 允許修改RTC和后備寄存器*/
35     RCC_LSEConfig( RCC_LSE_OFF ); /* 關閉外部低速時鍾,PC14+PC15可以用作普通IO*/
36     BKP_TamperPinCmd(DISABLE);  /* 關閉入侵檢測功能,PC13可以用作普通IO*/
37 
38     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
39     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
40     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
41     GPIO_Init(GPIOC, &GPIO_InitStructure);
42 
43     PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后備寄存器*/
44     //BKP_ITConfig(DISABLE);       /* 禁止TAMPER 中斷*/
45 
46     DS18B20_Reset();
47     return DS18B20_Check();
48 }
49 
50 /*******************************************************************************
51 * 函 數 名         : DS18B20_IO_IN
52 * 函數功能           : DS18B20_IO輸入輸出配置
53 * 輸    入         : 無
54 * 輸    出         : 無
55 *******************************************************************************/
56 void DS18B20_IO_IN(void)
57 {
58     GPIO_InitTypeDef  GPIO_InitStructure;
59     PWR_BackupAccessCmd( ENABLE );/* 允許修改RTC和后備寄存器*/
60     RCC_LSEConfig( RCC_LSE_OFF ); /* 關閉外部低速時鍾,PC14+PC15可以用作普通IO*/
61     BKP_TamperPinCmd(DISABLE);  /* 關閉入侵檢測功能,PC13可以用作普通IO*/
62 
63     GPIO_InitStructure.GPIO_Pin=DS18B20_Onboard;
64     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
65     GPIO_Init(DS18B20,&GPIO_InitStructure);
66 
67     PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后備寄存器*/
68 }
69 
70 void DS18B20_IO_OUT(void)
71 { 
72     GPIO_InitTypeDef  GPIO_InitStructure;
73     PWR_BackupAccessCmd( ENABLE );/* 允許修改RTC和后備寄存器*/
74     RCC_LSEConfig( RCC_LSE_OFF ); /* 關閉外部低速時鍾,PC14+PC15可以用作普通IO*/
75     BKP_TamperPinCmd(DISABLE);  /* 關閉入侵檢測功能,PC13可以用作普通IO*/
76 
77     GPIO_InitStructure.GPIO_Pin=DS18B20_Onboard;
78     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
79     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
80     GPIO_Init(DS18B20,&GPIO_InitStructure);
81 
82     PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后備寄存器*/
83 }

對DS18B20,按位、按字節讀取和寫數據:

 1 u8 DS18B20_Read_Bit(void)     // read one bit
 2 {
 3     u8 data;
 4     DS18B20_IO_OUT();//SET PC15 OUTPUT
 5     DS18B20_DQ_OUT=0;
 6     delay_us(2);
 7     DS18B20_DQ_OUT=1;
 8     DS18B20_IO_IN();//SET PC15 INPUT
 9     delay_us(12);
10     if(DS18B20_DQ_IN)data=1;
11     else data=0;
12     delay_us(50);
13     return data;
14 }
15 
16 u8 DS18B20_Read_Byte(void)    // read one byte
17 {
18     u8 i,j,dat;
19     dat=0;
20     for (i=1; i<=8; i++)
21     {
22         j=DS18B20_Read_Bit();
23         dat=(j<<7)|(dat>>1);
24     }
25     return dat;
26 }
27 
28 u8 DS18B20_Read_2Bit(void)    //read 2 bits
29 {
30     u8 i,dat;
31     dat=0;
32     for(i = 0;i < 2;i ++)  
33     {  
34         dat <<= 1;  
35         if(DS18B20_Read_Bit())
36     {
37         dat = dat|1;
38     }                      
39     }  
40     return dat;
41 }
42 
43 void DS18B20_Write_Bit(u8 dat)  //write one bit
44 {
45     u8 testb;
46     DS18B20_IO_OUT();//SET PG11 OUTPUT;
47     testb=dat&0x01;
48     if (testb)
49     {
50         DS18B20_DQ_OUT=0;// Write 1
51         delay_us(2);
52         DS18B20_DQ_OUT=1;
53         delay_us(60);
54     }
55     else
56     {
57         DS18B20_DQ_OUT=0;// Write 0
58         delay_us(60);
59         DS18B20_DQ_OUT=1;
60         delay_us(2);
61     }
62 }
63 
64 void DS18B20_Write_Byte(u8 dat)  //write one byte
65 {
66     u8 j;
67     u8 testb;
68     DS18B20_IO_OUT();//SET PC15 OUTPUT;
69     for (j=1; j<=8; j++)
70     {
71         testb=dat&0x01;
72         dat=dat>>1;
73         if (testb)
74         {
75             DS18B20_DQ_OUT=0;// Write 1
76             delay_us(2);
77             DS18B20_DQ_OUT=1;
78             delay_us(60);
79         }
80         else
81         {
82             DS18B20_DQ_OUT=0;// Write 0
83             delay_us(60);
84             DS18B20_DQ_OUT=1;
85             delay_us(2);
86         }
87     }
88 }

不匹配序號讀取溫度:

 1 u8 DS18B20_GetTemperature()
 2 {
 3     u16 temp;
 4     u8 a,b;
 5     u8 value;
 6 
 7     DS18B20_Reset();
 8     DS18B20_Check();
 9     DS18B20_Write_Byte(0xcc);// skip rom
10     DS18B20_Write_Byte(0xbe);// 讀存儲器命令轉換
11 
12     a=DS18B20_Read_Byte(); // LSB
13     b=DS18B20_Read_Byte(); // MSB
14 
15     temp=b;
16     temp=(temp<<8)+a;
17 
18     if((temp&0xf800)==0xf800)
19     {
20         temp=(~temp)+1;
21         value=temp*0.0625 + 128;  //如果小於0,則加128,負值范圍:128~255
22     }
23     else
24     {
25         value=temp*0.0625;    //正值的范圍:0~127(ds18b20的測溫范圍:-55~125攝氏度)
26     }
27     return value;        
28 }

讀序號並匹配序號,讀溫度:

u8 dsnum = 0;            //溫度傳感器的數量
u8 ds_ID[dsmax][8] = {0};   //ID
u8 dstemp[dsmax] = {0};     //溫度
/********************************************/
u8 DS18B20_SearchROM()  //搜索18B20
{
    u8 n,i,j,temp,CTW,num;
    u8 rom[64];
    u8 stack[dsmax];
    u8 id=0;
    n = 0;
    num = 0;
    do {
        DS18B20_Reset();
        DS18B20_Check();
        DS18B20_Write_Byte(0xf0);
        for(i=0; i<dsmax; i++)     //按字節
        {
            for(j=0; j<8; j++)   //按位
            {
                temp = DS18B20_Read_2Bit();
                temp &= 0x03;
                id >>=1;
                if(temp == 0x01) //這里先讀的是0,后讀的是1,表示有器件連接,並且它們這一位均是0
                {
                    DS18B20_Write_Bit(0);
                    rom[(i*8+j)] = 0;
                }
                else if(temp ==0x02)
                {
                    id |= 0x80;
                    DS18B20_Write_Bit(1);
                    rom[(i*8+j)] = 1;
                }
                else if(temp == 0x00) //有沖突位
                {
                    CTW = i*8+j+1;
                    if(CTW > stack[n]) //沖突位大於棧頂,寫0
                    {
                        DS18B20_Write_Bit(0);
                        rom[(i*8+j)] = 0;
                        zhan[++n] = CTW;
                    }
                    else if(CTW < stack[n])
                    {
                        id |= ((rom[(i*8+j)] & 0x01) << 7);
                        DS18B20_Write_Bit(rom[(i*8+j)]);

                    }
                    else if(CTW == stack[n])
                    {
                        id |= 0x80;
                        DS18B20_Write_Bit(1);
                        rom[(i*8+j)] = 1;
                        n--;
                    }
                }
                else
                {
                    return num;
                }
                delay_us(5);
            }
            ds_ID[num][i] = id;       //ds18B20的id64位
            id = 0;
        }
        num++;
    } while((stack[n] != 0) && (num < dsmax));
    dsnum = num;
    return num;
}

u8 DS18B20_GetDsTemperature(u8 dsID[8])
{
    u16 temp,n;
    u8 a,b;
    u8 value;

    DS18B20_Reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// 啟動溫度轉換
    DS18B20_Reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0x55); //發送匹配
    for(n=0; n<8; n++)
    {
        DS18B20_Write_Byte(dsID[n]);
    }
    delay_us(10);
    DS18B20_Write_Byte(0xbe);// 讀存儲器命令轉換
    a=DS18B20_Read_Byte(); // LSB
    b=DS18B20_Read_Byte(); // MSB
    temp=b;
    temp=(temp<<8)+a;
    if((temp&0xf800)==0xf800)
    {
        temp=(~temp)+1;
        value=temp*0.0625 + 128;  
    }
    else
    {
        value=temp*0.0625;                
    }
    return value;                                    
}

注意點:精度,時延,求平均值時數據溢出

 


免責聲明!

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



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