温度传感器
DS18B20
简介
DS18B20数字温度传感器接线方便,封装后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式。主要根据应用场合的不同而改变其外观。封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
特点
1、适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电
2、独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微
处理器与DS18B20的双向通讯。
3、DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网
多点测温。
4、DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一
只三极管的集成电路内。
5、温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃
6、可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃
和0.0625℃,可实现高精度测温。
7、在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms
内把温度值转换为数字,速度更快。
8、测量结果直接输出数字温度信号,以"一根总线"串行传送给CPU,同时可传送
CRC校验码,具有极强的抗干扰纠错能力。
9、负压特性:电源极性接反时,芯片不会因发热而烧毁, 但不能正常工作。
实物图
原理图
内部结构
(1) 64位(激)光刻只读存储器
光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列号。64位光刻ROM的排列是:开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。
(2) DS18B20温度转换规则
DS18B20的核心功能是它可以直接读出数字的温度数值。温度传感器的精度为用户可编程的9,10,11或12位,分别以0.5℃,0.25℃,0.125℃和0.0625℃增量递增。在上电状态下默认的精度为12位。
DS18B20启动后保持低功耗等待状态,当需要执行温度测量和AD转换时,总线控制器必须发出[44h]命令。转换完以后,产生的温度数据以两个字节的形式被存储到高速暂存器的温度寄存器中,DS18B20继续保持等待状态。
这是12位转化后得到的12位数据,存储在DS18B20的两个8位的RAM中,高字节的前5位是符号位,如果测得的温度大于0,这5位为‘0’,只要将测到的数值乘以0.0625即可得到实际温度;如果温度小于0,这5位为‘1’,测到的数值需要先减1再取反再乘以0.0625即可得到实际温度。
(3) DS18B20温度传感器的存储器
DS18B20温度传感器的内部存储器包括一个高度的暂存器RAM和一个非易失性的可电擦除的EEPROM,后者存放高温度和低温度触发器TH、TL和结构寄存器。
(4) 配置寄存器
存储器的第4位为配置寄存器,其组织见图8,用户可按表3所示设置R0和R1位来设定DS18B20的精度。上电默认设置:R0=1、R1=1(12位精度)。注意:精度和转换时间之间有直接的关系。暂存器的位7和位0-4被器件保留,禁止写入。
ROM指令
RAM指令
编程原理
DS18B20初始化
(1).数据线拉到低电平“0”。
(2).延时480微妙(该时间的时间范围可以从480到960微妙)。
(3).数据线拉到高电平“1”。
(4).延时等待80微妙。如果初始化成功则在15到60微妙时间内产生一个由DS18B20所返回的低电平“0”.根据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时判断。
(5).若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(3)步的时间算起)最少要480微妙。
DS18B20读时序
(1).将数据线拉低“0”。
(2).延时1微妙。
(3).将数据线拉高“1”,释放总线准备读数据。
(4).延时10微妙。
(5).读数据线的状态得到1个状态位,并进行数据处理。
(6).延时45微妙。
(7).重复1~7步骤,直到读完一个字节。
DS18B20写时序
(1).数据线先置低电平“0”
(2).延时15微妙。
(3).按从低位到高位的顺序发送数据(一次只发送一位)。
(4).延时60微妙。
(5).将数据线拉到高电平。
(6).重复1~5步骤,直到发送完整的字节。
(7).最后将数据线拉高。
大致过程
上面罗列了很多关于DS18B20的基础知识,但是在用于单片机时,用到的东西不是很多,主要是能读懂时序,控制好延时时间即可。
- 首先对DS18B20初始化,根据返回值检测DS18B20是否正常工作。
- 写字节,每次只能写入一位,先发送低位,所以需要循环八次
- 读字节函数,每次只能读1位
- 发送温度转换控制指令
- 发送读取RAM温度数据指令
- 处理好温度数据
- 用数码管动态显示
具体细节请看下方代码
代码实现
main函数
#include<reg52.h>
#include<temp.h>//调用编写好的头文件
typedef unsigned char u8;
typedef unsigned int u16;
sbit LSA=P2^2;//位定义,实现数码管位选
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 DisplayData[8];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示数字0~9
void delay(u16 i) //延时函数
{
while(i--);
}
void datapros(int temp) //处理数据函数
{
float tp;
if(temp<0)
{
DisplayData[0]=0x40;//显示符号
temp=temp-1; //先减一再取反
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5; //+0.5是为四舍五入,*100为了保留两位小数,因为tp是浮点型数据,而temp是整型数据 ,转换为整型时会自动舍去小数点后的数
}
else
{
DisplayData[0]=0x00; //显示符号
tp=temp;
temp=tp*0.0625*100+0.5;
}
DisplayData[1]=smgduan[temp%100000/10000];//显示百位
DisplayData[2]=smgduan[temp%10000/1000]; //显示十位
DisplayData[3]=smgduan[temp%1000/100]|0x80;//显示个位和小数点
DisplayData[4]=smgduan[temp%100/10];//显示小数点后一位
DisplayData[5]=smgduan[temp%10/1];// 显示小数点后第二位
}
void DigDisplay()
{
u8 i;
for(i=0;i<6;i++) //数码管位选,通过动态扫描,达到一种静态显示效果
{
switch(i)
{
case(0):LSA=1;LSB=1;LSC=1;break;
case(1):LSA=0;LSB=1;LSC=1;break;
case(2):LSA=1;LSB=0;LSC=1;break;
case(3):LSA=0;LSB=0;LSC=1;break;
case(4):LSA=1;LSB=1;LSC=0;break;
case(5):LSA=0;LSB=1;LSC=0;break;
}
P0=DisplayData[i];
delay(100);
P0=0x00;//消影
}
}
void main()
{
while(1)
{
datapros(Ds18b20ReadTemp()); //将读取到的温度数据处理,存储到DisplayData中
DigDisplay();//显示温度
}
}
temp函数文件
#include<temp.h> //包含编写好的头文件
void Delay1ms(uint y) //延时yms函数
{
uint x;
for(;y>0;y--)
{
for(x=110;x>0;x--);
}
}
uchar Ds18b20Init() //DS18B20初始化函数
{
uchar i;
DSPORT=0;//先将数据线拉低
i=70;
while(i--);//延时642ms,也可以使用延时函数
DSPORT=1;//再将数据线拉高
i=0; //变量清零
while(DSPORT)//如果DS18B20能正常工作则会使数据线拉低退出循环
{
Delay1ms(1);
i++;
if(i>5)
{
return 0;//如果5ms没有终止循环则自动退出循环,且返回0
}
}
return 1; //正常工作返回1
}
void Ds18b20WriteByte(uchar dat) //DS18B20写字节函数
{
uint i,j;
for(j=0;j<8;j++) //循环写8次
{
DSPORT=0; //数据线拉低
i++;//延时
DSPORT=dat&0x01; //前七位均变为0,只保留dat的最后一位
i=6;
while(i--);//延时68微秒
DSPORT=1; //拉高数据线
dat>>=1; //数据右移一位,最低位舍弃,最高位补0
}
}
uchar Ds18b20ReadByte() //DS18B20读字节函数
{
uchar byte='0',bi;
uint i,j;
for(j=8;j>0;j--)
{
DSPORT=0; //拉低数据线
i++; //延时
DSPORT=1; //拉高数据线
i++; //延时大约6微秒
i++; //延时
bi=DSPORT; //将DS18B20发送的数据给bi
byte=(byte>>1)|(bi<<7);// 使先发来的数据移到高位,再依次右移,从而得到正确的数据
i=4;
while(i--);//延时
}
return byte;//返回读取到的数据
}
void Ds18b20ChangeTemp() //发送温度转换指令函数
{
Ds18b20Init(); //初始化
Delay1ms(1); //延时1ms
Ds18b20WriteByte(0xcc); //发送ROM指令
Ds18b20WriteByte(0x44); //发送RAM指令 温度转换
//为了连续显示就不加延时
}
void Ds18b20ReadTempCon() //发送读取RAM温度数据指令
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0xbe);
}
int Ds18b20ReadTemp()//温度读取函数
{
int temp=0;
uchar tmh,tml;
Ds18b20ChangeTemp();
Ds18b20ReadTempCon();
tml=Ds18b20ReadByte(); //读取数据
tmh=Ds18b20ReadByte();
temp=tmh;
temp<<=8; //使高八位数据左移八位
temp|=tml; //组合低八位和高八位数据
return temp; //返回数据
}
头文件
#ifndef __TEMP_H_
#define __TEMP_H_
#include<reg52.h>
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
sbit DSPORT=P3^7;
void Delay1ms(uint y);
uchar Ds18b20Init();
void Ds18b20WriteByte(uchar dat);
uchar Ds18b20ReadByte();
void Ds18b20ChangeTemp();
void Ds18b20ReadTempCon();
int Ds18b20ReadTemp();
#endif