读数据时序
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时,温度为正;