1 DS18B20介绍
简介:
DS18B20是美国DALLAS半导体公司推出得第一片支持“单总线”接口的温度传感器,具有微型化、低功耗、抗干扰能力强、易配处理器的优点,可直接将温度转化成穿行数字信号。
特性:
- 适应电压范围宽:3.0~5.5V范围内。
- 单线接口方式,仅需一根数据线。
- 多点组网,多个芯片连接在唯一的三线上。
- 不需要外围器件,高度集成化。
- 测温范围-55度-125度,-10度到85度内的精确度可达0.5度。
- 可编程分辨率9~12位,对应精度位0.5度,0.25度,0.125度,9位时候的转换时间93.7ms,12位转换时间750ms。
- 直接输出数字信号,同时传送CRC校验码。
- 电源极性接反不会损坏电路,不能工作。
引脚介绍:
DS18B20有两种封装,三脚TO-92直插式和八角SOIC贴片式,如下图:
引脚定义:
硬件连接:
先介绍一下单总线技术,单总线技术采用一条信号线,既可以传输时钟,又可以传输数据,并且是双向传输,线路简单,硬件开销少,成本低,便于扩展和维护。单总线一般要钱外接一个约5k欧姆的上拉电阻,典型的接法如下:
DS18B20的指令:
33H 读ROM(传感器的编码,64位地址)
55H 匹配ROM,发出此命令之后接着发出64位ROM编码,访问单总线上于该编码对应的芯片并使之做出反应。
F0H 搜索ROM。用于确定挂接在同一总线上的芯片个数。
CCH 跳过ROM,忽略64位地址,直接向DS18B20发送温度变换命令
ECH 告警搜索命令,执行后只有温度超过设定值上限或者下限的芯片才反应。
如果主机只对一个DS18B20操作就可以跳过ROM命令直接进行温度转换和读取操作。
(1)44H 温度转换
(2)BEH 读暂存器
(3)4EH 写暂存器
(4)48H 复制暂存器
(5)B8H 重调E2PROM
(6) B4H 读供电方式
温度数据获取:
DS18B20在出厂时默认配置是12位,高位是符号位,温度值占11位,单片机读取一次16位的数据,然后将低11位转换成十进制数后乘以0.0625即可得到实际温度值。前5位是符号位,这五位同时变化,当前五位是1是温度是负值,需要取反加一在乘以0.0625,当前5位是0时为正直,直接将测量结果乘以0.0625即可。
工作时序:
时序图中的各总线状态
- 初始化
先将数据线置高电平
延时(尽可能短一些)
数据线拉低
延时750us
数据线拉高
延时等待。(如果初始化成功会在15ms-60ms内产生一个由DS18B20返回的低电平)
CPU读取低电平后。继续延时,从发出高电平算起至少480us
将数据线再次拉高结束
程序示例:
unsigned char Ds18b20Init()
{
unsigned int i;
DSPORT=0; //?????480us~960us
i=70;
while(i--);//??642us
DSPORT=1; //??????,??DS18B20???????15us~60us?????
i=0;
while(DSPORT) //??DS18B20????
{
i++;
if(i>5000)//??>5MS
return 0;//?????
}
return 1;//?????
}
- DS18B20写数据
数据线拉低
延时15us
从低位开始发数据
延时45us
数据线拉高
重复以上步骤直到发送一个字节
最后将数据线拉高
程序示例:
void Ds18b20WriteByte(unsigned char dat)
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0; //???????????????1us
i++;
DSPORT=dat&0x01; //????????,??????
i=6;
while(i--); //??68us,??????60us
DSPORT=1; //??????,??1us??????????????????
dat>>=1;
}
}
- 读数据时序
将数据线拉高
延时2us
将数据拉低
延时6us
数据线拉高
延时4us
读数据线的一个状态
延时30us
重复前几步
程序示例:
unsigned char Ds18b20ReadByte()
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j--)
{
DSPORT=0;//??????1us
i++;
DSPORT=1;//??????
i++;
i++;//??6us??????
bi=DSPORT; //????,????????
/*?byte????,??????7???bi,???????????0?*/
byte=(byte>>1)|(bi<<7);
i=4; //???????48us?????????
while(i--);
}
return byte;
}
2 温度传感器DS18B20仿真实例
Proteus仿真电路:
源代码:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char code display[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char com[]={0x01,0x02,0x04,0x08};
unsigned char num,num2=0,time[4]={0,0,0,0};
sbit DSPORT=P1^2;
int temp;
/******************/
void Delay1ms(unsigned int y)
{
unsigned int x;
for(y;y>0;y--)
for(x=110;x>0;x--);
}
unsigned char Ds18b20Init()
{
unsigned int i;
DSPORT=0; //?????480us~960us
i=70;
while(i--);//??642us
DSPORT=1; //??????,??DS18B20???????15us~60us?????
i=0;
while(DSPORT) //??DS18B20????
{
i++;
if(i>5000)//??>5MS
return 0;//?????
}
return 1;//?????
}
void Ds18b20WriteByte(unsigned char dat)
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0; //???????????????1us
i++;
DSPORT=dat&0x01; //????????,??????
i=6;
while(i--); //??68us,??????60us
DSPORT=1; //??????,??1us??????????????????
dat>>=1;
}
}
unsigned char Ds18b20ReadByte()
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j--)
{
DSPORT=0;//??????1us
i++;
DSPORT=1;//??????
i++;
i++;//??6us??????
bi=DSPORT; //????,????????
/*?byte????,??????7???bi,???????????0?*/
byte=(byte>>1)|(bi<<7);
i=4; //???????48us?????????
while(i--);
}
return byte;
}
void Ds18b20ChangTemp()
{
int i = 50;
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //??ROM????
Ds18b20WriteByte(0x44); //??????
while(i != 0)
{
i--;
}
}
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //??ROM????
Ds18b20WriteByte(0xbe); //????????
}
int Ds18b20ReadTemp()
{
int temp=0;
unsigned char tmh,tml;
Ds18b20ChangTemp(); //???????
Ds18b20ReadTempCom(); //????????????????
tml=Ds18b20ReadByte(); //??????16?,?????
tmh=Ds18b20ReadByte(); //?????
temp=tmh;
temp<<=8;
temp|=tml;
return temp;
}
void main()
{
int tp;
int i= 0;
TMOD=0x01;
TH0=(65536-917)/256;
TL0=(65536-917)%256;;
EA=1;
ET0=1;
TR0=1;
while(1){
temp = Ds18b20ReadTemp();
if(temp < 0)
{
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
tp=temp;
temp=tp*0.0625*100+0.5;
}
time[0] = temp / 10000;
time[1] = temp % 10000 / 1000;
time[2] = temp % 1000 / 100;
time[3] = temp % 100 / 10;
Delay1ms(600);
}
}
void Timer0() interrupt 1
{
TH0 = (65536-917)/256;
TL0 = (65536-917)%256;;
num++;
if(num==10){
num=0;
P0=~com[num2];
P2=0xff;
if(num2==2)
{P2=display[time[num2]]|0x80;}
else
{P2=display[time[num2]];}
num2++;
if(num2>=4)
num2=0;
}
}
欢迎加入单片机学习交流群:277053582,群里会发布一些学习资源,小伙伴们也可以上传自己的学习资源供大家使用。