DS18B20读取温度,序号匹配

时间:2022-08-19 01:00:06
 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;                                    
}

注意点:精度,时延,求平均值时数据溢出