1.DS18B20介绍
DS18B20温度传感器是单总线器件,一根线上可以挂接多个DS18B20,在生活中运用很多。
2.DS18B20特点
(1)单线通信
(2)每个DS18B20都有唯一的64位序列码存在板载ROM中。(多机挂接时找对应DS18B20)
(3)温度范围:-55-125度
(4)温度传感器可以设置9-12位,12位为0.0625度(就是只有变化0.0625数值才会变化加一)
同理9位 0.5度,10位 0.25度,11位 0.125度
3.器件原理图
1与3口为接地与电源,2口为数据转输线
4.单总线转输
(1)单总线信号类型:
复位,存在脉冲,读0,读1,写0,写1
这些信号只有存在脉冲是DS18B20发出的,其余是总线控制器发出的
数据从最低位开始存。
5.发送方法
(1)初始化时序
主机与DS18B20的任何通信都需要进行初始化程序
初始化时序包括复位DS18B20和接收DS18B20的返回的存在信号。
复位:总线拉低480us以上,总线上的器件都被复位。然后拉高,等待15-60us
存在:DS18B20返回60-240us的低点平存在信号。
(2)写0与写1
就是将总线控制拉低,然后由拉低的时间取确认写0还是写1,如果拉低60到120us为写0,15us后为写1,然后拉高间隔1us。
(3)读时序
同样是总线控制拉低,然后15us内读取到数据,读一位数据要保存60us+。
6.温度寄存器内容
(1)0-1个字节
用于存储温度数据,LSB为高位,MSB为低位。
(2)2-3个字节
TH为最高上限报警位
TL为最低下限报警位
(3)4字节
主要配置DS18B20工作在多少位
如下就R1与R0可以改变配置
(4)5-8字节
暂时无用
(5)EEPROM为寄存器,断电数据也不会断,故我们可以设置EEPROM后传给BS18B20。
7.步骤
(1)初始化时序
(2)发送ROM指命(寻找单总线上的BS18B20的地址)
(3)DS18B20的功能指命
8.特殊指命
(1)0xcc,忽略ROM指命
当一条总线上只有一个BS18B20时就可以使用,因为不需要找地址了。
当是有多个显然不行,上面的所以BS18B20都会被开启使用。
(2)0x44,温度转换
启动一次温度转换,传感器收集到的温度数据直接以2个字节的形式被放在高速寄存器的第0-1位中。
(3)0xbe,读暂存器的内容
读取将从0开始,然后一直读下去,直到发送复位电路停止读取。
(4)0x4e,写暂存器TH,TL,模式的内容
写直接从TH位置开始写,直到写完配置暂存器后停止。
(5)0x48,拷贝暂存器
将TH,TL,配置暂存器的内容写到EEPROM,而与之对应的就是0xB8,将EEPROM数据传回。
#include <reg52.h>
#include <intrins.h>
sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4;
sbit DS = P3^7;
unsigned char miao; //全局变量位,控制显示
unsigned char smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay(unsigned char us) //进入11.95us,执行一次6.5us
{
while(us--);
}
void delay2(unsigned int z) //延时函数2,delay(1000)=1s
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
void timefrist() //中断初始化
{
EA = 1;
ET0 = 1;
TR0 = 1;
TMOD |= 0x01;
TH0 = 0xED;
TL0 = 0xFF;
}
void DigDisplay(unsigned char h) //显示函数
{
unsigned char a=h%10;
unsigned char b=h/10%10;
unsigned char c=h/100;
static unsigned char wei=0;
switch(wei)
{
case 0: LA=1;LB=1;LC=1;P0 = smgduan[c];break;
case 1: LA=0;LB=1;LC=1;P0 = smgduan[b];break;
case 2: LA=1;LB=0;LC=1;P0 = smgduan[a];break;
}
wei++;
if(wei==3)
{
wei = 0;
}
}
void timer0() interrupt 1 //中断函数150ms不断显示
{
TH0 = 0xED;
TL0 = 0xFF;
DigDisplay(miao);
}
bit dsdirst() //初始化时序
{
bit i;
DS = 1;
_nop_(); //DS=1的时间要有
DS = 0;
delay(75); //拉低480us以上
DS = 1; //释放总线
delay(4); //等待15-60us
i = DS; //接收BS18B20的存在信号
delay(20); //60到240的us的存在信号
DS =1; //释放总线
_nop_();
return (i); //返回存在信号
}
void writeone(unsigned char dat) //写一个字节
{
unsigned char i; //初始化前已经拉高了DS
for(i=0;i<8;i++)
{
DS = 0;
_nop_(); //拉低1us
DS = dat & 0x01; //从最低有效位开始
delay(10); //同时满足写0与写1要求
DS = 1; //释放总线,准备下一次输入数据
_nop_();
dat >>= 1; //不断右移,把下一位对应的最低位
}
}
unsigned char readone() //读一个字节
{
unsigned char i,j,dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();
DS = 1; //拉低后释放总线交给DS18B20控制
_nop_();
j = DS; //读数据一位
delay(10); //读一位数据至少要60us以上
DS = 1; //重新交给控制器
_nop_();
dat = (j<<7) | (dat>>1); //j写到最高位给dat后然后dat右移到最低位
}
return(dat);
}
void main()
{
unsigned int i;
unsigned char L,H;
timefrist(); //定时器0初始
while(1)
{
dsdirst(); //每次通信都要初始化
writeone(0xcc); //跳跃ROM(寻址)指命,因为51上只有一个DS18B20
writeone(0x44); //发送温度转换指命,存储在寄存器内
dsdirst(); //重新初始化
writeone(0xcc); //跳跃ROM(寻址)指命,因为51上只有一个DS18B20
writeone(0xbe); //读暂存器的内容,从第0个字节开始
L = readone(); //读第一个字节(温度高位)
H = readone(); //读第2个字节(温度低位)
i = H;
i <<= 8; //这里为把高8位与低8位合起来
i |= L;
i = i * 0.0625 *10 + 0.5; //0.0625为12位分辨率,*10是为了显示小数后一位
delay2(1000); //延时1s,再检测一次温度
miao = i; //i赋予全局miao显示
}
}