大家好,我是刘士铭,今天继续分享工作所用到的温度传感器DS18B20,一下文章为在网络上搜集整理后添加自己的理解更改完善所得,如果侵权请联系删除,谢谢。
DSI8B20接收到温度转换命令后,开始启动转换。转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的0,1字节。单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式以0.062 5℃/LSB形式表示。温度值格式如表2.2.1所示,其中“S”为标志位,对应的温度计算:当符号位S=0时,直接将二进制位转换为十进制,得到的温度值即为正温度值;当S=1时,测得的温度是零下,DS18B20保存的是温度的补码值,需要对其低8位(LS Byte)取反加一变成原码。再计算十进制值,得到的温度值即为负温度值。
DS18B20的核心功能是直接温度-数字测量。其温度转换可由用户自定义为9、10、11、12位精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率。值得注意的是,上电默认为12位转换精度。DS18B20上电后工作在低功耗闲置状态下。主设备必须向DS18B20发送温度转换命令[44h]才能开始温度转换。温度转换后,温度转换的值将会保存在暂存存储器的温度寄存器中,并且DS18B20将会恢复到闲置状态。如果DS18B20是由外部供电,当发送完温度转换命令[44h]后,主设备可以执行“读数据时序”。若此时温度转换正在进行DS18B20将会响应“0”,若温度转换完成则会响应“1”。如果DS18B20是由“寄生电源”供电,该响应的技术将不能使用,因为在整个温度转换期间,总线必须强制拉高。
DS18B20的温度输出数据时在摄氏度下校准的;若是在华氏度下应用的话,可以用查表法或者常规的数据换算。温度数据以一个16位标志扩展二进制补码数的形式存储在温度寄存器中(详见图2)。符号标志位(S )温度的正负极性:正数则S=0,负数则S=1。如果DS18B20被定义为12位的转换精度,温度寄存器中的所有位都将包含有效数据。若为11位转换精度,则bit 0为未。
由于DS18B20转换后的代码并不是实际的温度值,所以要进行计算转换。温度高字节(MS Byte)高5位是用来保存温度的正负(标志为S的bit11~bit15),高字节(MS Byte)低3位和低字节来保存温度值(bit0 ~ bit10)。其中低字节(LS Byte)的低4位来保存温度的小数位(bit0 ~ bit 3)。由于本程序采用的是0.0625的精度,小数部分的值,可以用后四位代表的实际数值乘以0.0625,得到真正的数值,数值可能带几个小数位,所以采取小数舍入,保留一位小数即可。也就说,本系统的温度精确到了0.1度。
算法核心:首先程序判断温度是否是零下,如果是,则DS18B20保存的是温度的补码值,需要对其低8位(LS Byte)取反加一变成原码。处理过后把DS18B20的温度Copy到单片机的RAM中,里面已经是温度值的Hex码了,然后转换Hex码到BCD码,分别把小数位,个位,十位的BCD码存入RAM中。
如:0550H 是+85°C 0191H:+25.0625°C FC90H是-55°C
(1)DS18B20控制方法(DS18B20有六条控制命令):
(2)温度转换 44H 启动DS18B20进行温度转换
(3)读暂存器 BEH 读暂存器9位二进制数字
(4)写暂存器 4EH 将数据写入暂存器的TH、TL字节
(5)复制暂存器 48H 把暂存器的TH、TL字节写到E2RAM中
(6)重新调E2RAM B8H 把E2RAM中的TH、TL字节写到暂存器TH、TL字节
(7)读电源供电方式 B4H 启动DS18B20发送电源供电方式的信号给主CPU
Void delay_18B20(us)
{
While(us--);
}
1. 初始化
(1) 先将数据线置高电平“1”。
(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
(3) 数据线拉到低电平“0”。
(4) 延时750微秒(该时间的时间范围可以从480到960微秒)。
(5) 数据线拉到高电平“1”。
(6) 延时等待(如果初始化成功则在15到60微妙时间之内产生一个由DS18B20所返回的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
(8) 将数据线再次拉高到高电平“1”后结束。
void ds1820rset() //ds1820复位
{
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
2. 写数据操作
(1) 数据线先置低电平“0”。
(2) 延时确定的时间为15微秒。
(3) 按从高位到低位的顺序发送字节(一次只发送一位)。D7到D0的次序
(4) 延时时间为45微秒。
(5) 将数据线拉到高电平。
(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7) 最后将数据线拉高。
void ds1820wrdata(uchar wdata) /*写数据*/
{
unsigned char I,temp=0x00;
for (i=8;i》0;i--)
{ DQ=0;
delay_18B20(15)
temp=1《《i-1;
DQ=wdata&temp;
delay_18B20(45);
DQ=1;
}
}
3. 读数据操作
(1)将数据线拉高“1”。
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时3微秒。
(5)将数据线拉高“1”。
(6)延时5微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时60微秒。
读一位二进制数
bit ds_read_bit(void)
{
bit dat;
DQ=0;
delay_18B20(2);
DQ=1;
delay_18B20(3);
dat=DQ;
delay_18B20(100);
return(dat);
}
读一个字节,8位二进制数
uchar ds1820readdata() //读数据
{
unsiged char i,j,value=0;
for(i=0;i《8;i++)
{
j=ds_read_bit();
value |=j《《7-i;
}
return(value);
}
Ds1820_Bus = 0; //产生下降沿,进入写时序(15us内送上数据)
Ds1820_Bus = data_1820&0x01; //从低位开始送数
Delay_X15us(3);//延时45us,保证18b20采样到数据
Ds1820_Bus = 1; //拉高电平完成送数
Delay_X15us(1);//连续送数要间隔至少1us(这里15us)
data_1820》》=1;//移位