DS18B20介绍
•DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
•测温范围:-55°C到 +125°C
•通信接口:1-Wire(单总线)
•其它特征:可形成总线结构、内置温度报警功能、可寄生供电
![](https://i-blog.csdnimg.cn/blog_migrate/8ab00d6da2f72384cbc98b6d01ef5893.png)
引脚及应用电路
![](https://i-blog.csdnimg.cn/blog_migrate/9390376fa2d7709cba74154efead52fe.png)
内部结构框图
![](https://i-blog.csdnimg.cn/blog_migrate/9cdb4b68dcf4857e9d92afca8a3cf8c7.png)
•64-BIT ROM:作为器件地址,用于总线通信的寻址
•SCRATCHPAD(暂存器):用于总线的数据交互
•EEPROM:用于保存温度触发阈值和配置参数
存储器结构
![](https://i-blog.csdnimg.cn/blog_migrate/8b26428526c0010ec94be5ca4230f27d.png)
单总线介绍
•单总线(1-WireBUS)是由Dallas公司开发的一种通用数据总线
•一根通信线:DQ
•异步、半双工
•单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
单总线电路规范
![](https://i-blog.csdnimg.cn/blog_migrate/11f212a9323526b6a10c6af82475269d.png)
单总线时序结构
初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线
![](https://i-blog.csdnimg.cn/blog_migrate/67a74726a3c8507a2cc067723cbdc098.png)
•发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
![](https://i-blog.csdnimg.cn/blog_migrate/2959ff378eb92ba82a2b6d7877a7b7f7.png)
•接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us
![](https://i-blog.csdnimg.cn/blog_migrate/278781620b7061a82c5eb95d795b99c9.png)
单总线时序结构
![](https://i-blog.csdnimg.cn/blog_migrate/b459bf72f6bd326665623b220a6b462c.png)
DS18B20操作流程
•初始化:从机复位,主机判断从机是否响应
•ROM操作:ROM指令+本指令需要的读写操作
•功能操作:功能指令+本指令需要的读写操作
![](https://i-blog.csdnimg.cn/blog_migrate/84bf57d9e7ac6235aa5868c0699ab307.png)
DS18B20数据帧
![](https://i-blog.csdnimg.cn/blog_migrate/e3e6f9f0b527463e8738a01bff0c8b19.png)
温度存储格式
![](https://i-blog.csdnimg.cn/blog_migrate/1bed48675995efb54b472ffa5e95b62d.png)
DS18B20显示温度
1)主程序
#include <regx52.h>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
float T;
void main ( )
{
DS18B20_ConvertT();
Delay(1000);
LCD_Init( );
LCD_ShowString(1,1,"Temperature:");
while(1)
{
DS18B20_ConvertT();
T=DS18B20_ReadT();
if(T<0)
{
LCD_ShowChar(2,1,'-');
T=-T;
}
else
{
LCD_ShowChar(2,1,'+');
}
LCD_ShowNum(2,2,T,3);
LCD_ShowChar(2,5,'.');
LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);
}
}
2)DS18B20
#include <regx52.h>
#include "OneWire.h"
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
void DS18B20_ConvertT(void)
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte( DS18B20_CONVERT_T );
}
float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
TLSB=OneWire_ReceiveByte();
TMSB=OneWire_ReceiveByte();
Temp=(TMSB<<8)|TLSB;
T=Temp/16.0;
return T;
}
3)OneWire
#include <regx52.h>
sbit OneWire_DQ=P3^7;
unsigned char OneWire_Init(void)
{
unsigned char i,AckBit;
EA=0; //关闭定时器防止影响时序
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i); //Delay 500us
OneWire_DQ=1;
i = 32;while (--i); //Delay 70us
AckBit=OneWire_DQ;
i = 247;while (--i); //Delay 500us
EA=1;
return AckBit;
}
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
EA=0;
OneWire_DQ=0;
i = 4;while (--i); //Delay 10us
OneWire_DQ= Bit;
i = 24;while (--i); //Delay 50us
EA=1;
OneWire_DQ=1;
}
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
EA=0;
OneWire_DQ=0;
i = 2;while (--i); //Delay 5us
OneWire_DQ=1;
i = 2;while (--i); //Delay 5us
Bit=OneWire_DQ;
i = 24;while (--i); //Delay 50us
EA=1;
return Bit ;
}
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for( i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<<i));
}
}
unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte=0x00;
for( i=0;i<8;i++)
{
if(OneWire_ReceiveBit())(Byte|=(0x01<<i));
}
return Byte;
}
DS18B20温度显示Proteus仿真
![](https://i-blog.csdnimg.cn/blog_migrate/339a0bcdf6325b759e62b2a29ccc25c9.png)
DS18B20温度报警装置
1)主程序
#include <regx52.h>
#include "LCD1602.h"
#include "AT24C02.h"
#include "Key.h"
#include "Delay.h"
#include "DS18B20.h"
float T,TShow;
char THigh,TLow;
unsigned char KeyNum;
void main ( )
{
DS18B20_ConvertT();
THigh=AT24C02_ReadByte(0);
TLow=AT24C02_ReadByte(1);
Delay(1000);
if(THigh>125 || TLow<-55 || THigh<=TLow)
{
THigh=20; //如果阈值非法,则设为默认值
TLow=15;
}
LCD_Init();
LCD_ShowString(1,1,"T:");
LCD_ShowString(2,1,"TH:");
LCD_ShowString(2,9,"TL:");
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
AT24C02_WriteByte(0,THigh);
Delay(5);
AT24C02_WriteByte(1,TLow);
Delay(5);
Timer0_Init();
while(1)
{
DS18B20_ConvertT();
T=DS18B20_ReadT();
if(T<0)
{
LCD_ShowChar(1,3,'-');
TShow=-T;
}
else
{
LCD_ShowChar(1,3,'+');
TShow=T;
}
LCD_ShowNum(1,4,TShow,3);
LCD_ShowChar(1,7,'.');
LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);
KeyNum=Key();
if(KeyNum)
{
if(KeyNum==1)
{
THigh++;
if(THigh>125){THigh=125;}
}
if(KeyNum==2)
{
THigh--;
if(THigh<=TLow){THigh++;}
}
if(KeyNum==3)
{
TLow++;
if(TLow>=THigh){TLow--;}
}
if(KeyNum==4)
{
TLow--;
if(TLow<-55){TLow=-55;}
}
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
}
if(T>THigh)
{
LCD_ShowString(1,13,"OV:H");
}
else if(T<TLow)
{
LCD_ShowString(1,13,"OV:L");
}
else
{
LCD_ShowString(1,13," ");
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=20)
{
T0Count=0;
Key_Look();
}
}
2)OneWire.c中需要关闭定时器防止影响单总线的时序接收
![](https://i-blog.csdnimg.cn/blog_migrate/b764275b683c6ff20820e93fda22f2e8.png)
3)Proteus仿真
![](https://i-blog.csdnimg.cn/blog_migrate/21f6f49a95042441c7c251cbf062658a.png)