DS18B20简介
DS18B20是常用的数字温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。 DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。
主要根据应用场合的不同而改变其外观。封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
单个18B20实现温度测试步骤
该文档所用程序为FREESCALE JM60单片机,总线时钟为8M,若要移植到其它MCU上,需要将时间重新调节,或者更改总线时钟频率的输出;
电路图
DS18B20工作协议:初始化,存储器操作命令,处理数据;
在关于时序的编写中,for循环中的NOP指令,和单独调用的NOP指令所用时间完全不同;NOP占用1/总线时
钟的时间;如JM60的总线时钟为8M,则NOP指令一定占用0.125US,而将NOP放在FOR循环中,由于FOR的判断指令,加法指令,以及转子程序等等消耗的时间很长,远远大于一个NOP的指令,此时,若要获得执行代码的精确时间,最好用示波器观察,再得出最直接的结果;
在单片机的使用中,不要用浮点数,全部用整数代替,在数据进行移位作乘法时,一定要注意数据有没有越界,算出来的数很容易出现错误,并且在出现浮点数时,可以将数据放大到一定的精度,然后在显示时,将小数点移到对应的位置即可;
在数据做乘法容易越界时,一般将其赋给一个字节多的整数,作为中间变量运算,在确保数据不会越界后,再将其赋给最后结果;
初始化时序
初始化时序步骤:
1. 主机将端口设为输出,先发送一个高电平,然后再拉低,维持480-960US;(推荐500-600US)
2. 主机将端口设为输入,上拉电阻此时将电平拉高,主机等待60US-200US;(推荐100-150US)
3. 主机读取端口数据,低电平则初始化成功;高电平表示初始化失败;
4.读取数据完毕后,主机等待至少400US; (推荐450-500US)
注:
l 第四步很重要,读取初始化状态后,仍然延时400US才可以初始化完毕,否则传感器不能正常使用;
l 在这里注意端口需要不停地改变方向;在主机发送时,设为输出,主机接收时,设为输出;
/*****************18B20的初始化程序***************************/
byte INIT_18B20() {
byte DQ_RETURN=2;
DQ_OUT=1; //引脚设置为输出
DQ=1;
DELAY1(); //稍微延时,即可
DQ=0; //将电平拉低至少480uS,最大为960US
DELAY9(70);
DQ_OUT=0;
//设置为输入,设为输入15到60US
DELAY9(6); //等待18B20响应,如果为低电平表示初始化成功,维持60到240 //微秒
DQ_RETURN=DQ;
DELAY9(70); //读完数据后,仍然延时,至少480US
return(DQ_RETURN); //返回值为1,表示失败,返回值为0表示成功
}
端口写数据时序
1. 主机将电平拉高,稍微延时(推荐值:2US),然后拉低电平,产生一个下降沿,表示写数据开始;低电平维持至少1US;(此时推荐2US)
2. 此时,将要写的1或0放在数据线上;(从写数据第一步开始到现在,整个过程在15US之内完成;
3. 然后主机延时等待至少50US;(推荐60US)
4. 主机最后将电平拉高;
5. 每写两位数据之间的间隔要大于1US;
注:
l 在写步骤中,整个过程端口方向均为输出;
这里对时序要求高,最好用示波器调整出精确的时序;
/*****************向18B20写数据********************************/
void WRITE_18B20(unsigned char ch){
byte i;
for(i=0;i《8;i++) {
DQ_OUT=1; //端口设为输出,并给个拉低电平的下降沿
DQ=1;
DELAY1();
DQ=0; //拉低电平,并维持一微秒以上,表示要发送数据
DELAY1();
DELAY1();
//在15US内将要写的电平写在线上
if((ch&0x01)==1) //将数据按位取出,从LSB到MSB依次送出
DQ=1;
else
DQ=0;
ch=ch》》1;
DELAY9(8); //电平维持40US以上,18B20将在此时将数取出
DQ=1;
}
DQ=1; //最后将电平重新拉高
}
读数据时序
1. 主机将电平拉高,稍微延时(推荐2US),然后将电平拉低,产生一个下降沿,表示读数据;这个低电平至少维持1US,此处推荐2US;
2. 将端口方向设为输入,必须在下降沿之后的15US内将端口数据读取;此处推荐端口方向设为输入后,延时5US,读取端口数据;
3. 读取数据完毕后,延时60US即可;
4. 每两个数据位之间间隔大于1US;
注:
在这个时序内,要不断改变端口方向;
如果上拉电阻阻值合理设置,可以小于4.7K欧姆,利于提高时序速度; l
读数据和写数据都是8位,从LSB开始发送;
/***************从18B20取出字符*******************************/
byte READ_18B20(){
byte ch=0;
byte i;
for(i=0;i《8;i++){
DQ_OUT=1; //端口输出
DQ=1;
DELAY1(); //产生下降沿,至少维持一微秒
DQ=0;
DELAY1(); //将端口设为输入,等待读取
DQ_OUT=0; //在15US之内读取数据
ch=ch》》1;
//延时大概5US
DELAY5();
if(DQ)
ch=ch|0x80;
else
ch=ch&0x7f;
DELAY9(8);
//每两个读数据之间间隔要大于60US }
return(ch); //返回读到的数据
}
以上三段为底层基本函数;DELAY后面的数字DELAY1,DELAY5,DELAY9为延时的微秒时长; DQ设置为硬件连接的端口,DQ_OUT为端口方向的设置
然后就是调用函数了:
当数据线上还有一个18B20时,通常步骤如下:
初始化;
跳过ROM;
温度开始转换命令;
等待温度转换完成;//当使用18B20默认的12位转换精度,用时750MS,经检验,一般耗时比理论稍长;
初始化;
跳过ROM;
读暂存器命令;
将温度数据低八位,高八位依次取出;
初始化;//注:最后仍然要进行初始化
结束;
对应的函数如下
/********************温度开始转换命令程序*******************************/
byte TEMP_DETECT_18B20(){
byte dummy=2;
dummy=INIT_18B20(); //初始化
if(dummy==0){
WRITE_18B20(0XCC); //跳过ROM,不读地址,直接通讯
WRITE_18B20(0x44); //温度开始转换命令
}
return(dummy); //返回0表示成功初始化,开始转换温度
}
注:在开始转换命令和读取温度之间,若18B20忙于转换温度,电平为低电位;
转换完毕将电平拉高;若不想用DELAY等待温度转换,可读取DQ值,为1则表示转换完毕,可以开始读取数据了;
/****************读取温度命令程序***************************************/
uint TEMP_READ_18B20(){
byte dummy=0;
byte TEMH=0,TEML=0;
uint TEM_RESULT;
dummy=INIT_18B20(); //初始化
if(dummy==0){
WRITE_18B20(0XCC); //跳过ROM
WRITE_18B20(0xBE); //读暂存存储器的值命令
TEML=READ_18B20();
TEMH=READ_18B20(); //读温度的高8位和低八位
dummy=INIT_18B20(); //最后初始化,表示读取温度结束
}
TEM_RESULT=(TEML》》3)+(TEMH《《5); //分辨率为0.5°
TEM_RESULT=TEM_RESULT*5;
if((TEMH&0X80)!=0)
//最高位为1,则为负温度 ;;
// TEM_RESULT=~TEMP_RESULT+1; //温度为负,取补码
return(TEM_RESULT); //返回值为温度的十倍,小数点后一位
}
主函数中调用:
SIGNAL=TEMP_DETECT_18B20();
if(SIGNAL==0){
if(DQ) //此时端口为1,则表示转换完成
TEMP_RESULT=TEMP_READ_18B20(); //返回温度的十倍值
若时序错误,很有可能读出的数据位0XFF;若温度传感器烧坏,容易读到85°; l
使用默认12位转换精度,分辨率为0.0625°,此处不需要这么高的精度因此:
TEM_RESULT=(TEML》》3)+(TEMH《《5); //分辨率为0.5°
舍弃后面三位数据,并且只有11位是温度值,高八位中的前五位是符号位;
读取为1时温度为负;读取为0时,温度为正;