1.总思路:
DS18B20 的典型温度读取过程为:1.复位→2.发 SKIP ROM 命令(0XCC)→3.发开始转 换命令(0X44)→4.延时→5.复位→6.发送 SKIP ROM 命令(0XCC)→7.发读存储器命令 (0XBE)→8.连续读出两个字节数据(即温度)→9.结束。
2.初始化时序函数:
//初始化 void ds18b20_reset(void) { DS18B20_PORT=0;//第一步拉低 delay_10us(75);//第二步延时 DS18B20_PORT=1;//第三步拉高 delay_10us(2);//第四步延时 } //如果有相应(包括拉低,延时,拉高延时),返回0,没有相应返回1 u8 ds18b20_check(void) { u8 time_temp=0;//第五步拉低 //相应的拉低判断和延时时间长短判断 while(DS18B20&&time_temp<20)//用while循环判断,如果时间过长,则为没有相应 { //意思是在200us之内可以持续等待ds18b20拉低 time_temp++; delay_10us(1); } if(time_temp>=20) return 1;//确定没有相应 time_temp=0; delay_10us(2); while((!DS18B20)&&(time_temp<20)) { time_temp++; delay_10us(1); } if(time_temp>=20) return 1; return 0; }
3.写时序:
//写时序 void ds18b20_write_type(u8 dat) { u8 i=0; u8 temp=0;//为了接收dat并按位与传递 for(i=0;i<8;i++) { temp=dat&0x01;//得到dat最低位方法:dat与0x01进行按位与 dat>>=1;//每次移动一个位 if(temp)//写1时序时 { DS18B20_PORT=0;//第一步,拉低 _nop_();_nop_();//第二步,延时,因为只需要2us,则只能用2us DS18B20_PORT=1;//第三步,拉高 delay_10us(6);//第四步,延时 } else//写0时序时 { DS18B20_PORT=0;//第一步,拉低 delay_10us(6);//第二步,延时 DS18B20_PORT=1;//第三步,拉高 _nop_();_nop_(); //第四步,延时 } } }
4.读时序:
//读时序---一个字节
u8 ds18b20_read_bit(void) { u8 dat=0;//返回dat来判断读一还是零 DS18B20_PORT=1;//准备工作 _nop_();_nop_(); DS18B20_PORT=0;//第一步,拉低 _nop_();_nop_();//第二步,延时 if(DS18B20_PORT) dat=1;//此处是对1和0的判断,用if比较好 else dat=0;//如果DS18B20是低,则返回的dat为0 delay_10us(45); }
//读时序---将每个字节都写
u8 ds18b20_write_type(void) { u8 i=0;//for用到 u8 dat=0; u8 temp=0; for(i=0;i<7;i++) { temp=ds18b20_read_bit();//将读一个字节的值传递给temp dat=temp<<7;//将temp左移7位,传递给dat dat>>=dat;//向右移动一位,给下一个数做铺垫 } return dat;//返回读时序每一位的1或0 }
5.温度读取过程:
DS18B20 的典型温度读取过程为:1.复位→2.发 SKIP ROM 命令(0XCC)→3.发开始转 换命令(0X44)→4.延时→5.复位→6.发送 SKIP ROM 命令(0XCC)→7.发读存储器命令 (0XBE)→8.连续读出两个字节数据(即温度)→9.结束。
//DS18B20温度读取过程函数
float ds18b20_read_temperture(void) { float temp;//读取并传递最终的值 u8 dath=0;//高字节,即高八位 u8 datl=0;//低字节,即第八位 u16 value=0; ds18b20_reset();//第一步,复位 ds18b20_check();// 检测 ds18b20_write_byte(0xcc);//第二步,发0XCC命令 ds18b20_write_byte(0xbe);//第三步,发0x44 //第四步延时,可跳过,因为写函数里面自带延时 ds18b20_reset();//第五步,复位 ds18b20_check();// 检测 ds18b20_write_byte(0xcc);//第六步,发0XCC命令 ds18b20_write_byte(0xbe);//第七步,发0x44 //第八步 读两个字节,需要第八位+高八位, //高八位按位向左移八位才是真正的高八位, //并将此时的高八位和第八位相加,即是16位数据value //之后判断符合位,如果是负温度,需要&0xf800, //之后按位取反再+1,所得结果*0.0625, //因为温度是负数,所以注意带负号 datl=ds18b20_read_byte();//第八步,读低字节+ dath=ds18b20_read_byte();//高字节 value=(dath<<8)+datl;//合并为16位数据 if((value&0xf800)==0xf800)//判断符号位,负温度 { value=(~value)+1; //数据取反再加1 temp=value*(-0.0625);//乘以精度 } else //正温度 { temp=value*0.0625; } return temp; }