ds18b20读温度
DS1820 数字温度计提供温度读数,指示器件的温度
注意事项!!!!!!!!
访问DS18B20的事件序列如下所示:
第一步:初始化
第二步:ROM命令(紧跟任何数据交换请求)
第三步:DS18B20功能命令(紧跟任何数据交换请求)
每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DS18B20将不会响应。除了ROM搜索命令[F0h]和报警搜索命令[ECh]之外。当执行完这些ROM命令之后,主设备必须回到上述步骤中的第一步。
每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DS18B20将不会响应。除了ROM搜索命令[F0h]和报警搜索命令[ECh]之外。当执行完这些ROM命令之后,主设备必须回到上述步骤中的第一步。
每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DS18B20将不会响应。除了ROM搜索命令[F0h]和报警搜索命令[ECh]之外。当执行完这些ROM命令之后,主设备必须回到上述步骤中的第一步。
综述
DS1820 有三个主要的数据部件
1.64 位激光(lasered)ROM;
2.温度灵敏元件
3.非易失性温度告警触发器TH 和TL
器件从单线的通信线取得其电源在信号线为高电平的时间周期内把能量贮存在内部的电容器中在单信号线为低电平的时间期内断开此电源直到信号线变为高电平重新接上寄生电容电源为止作为另一种可供选择的方法
DS1820 也可用外部5V 电源供电
特性
- 独特的单线接口只需1 个接口引脚即可通信
- 内部温度采集精度可以由用户自定义为9-Bits至12-Bits。上电默认设置:12 位精度。
- 测量范围从-55℃至+125℃(-67℉至+257℉);温度范围超过-10℃至85℃之外时具有±0.5℃的精度。在1 秒典型值内把温度变换为数字
- 多点(multidrop )能力使分布式温度检测应用得以简化
- 可用数据线供电,不需备份电源,不需要–外部元件
- 用户可定义的非易失性的温度告警设置
针脚
供电方式
两种供电方式:寄生电源(数据线供电),和外部5v电源供电
使用寄生电源时(数据线供电),在寄生电源模式下,1-Wire总线和Cpp可以提供给DS18B20足够的电流来完成各种工作,但在进行温度转换或暂存寄存器中的值拷贝至EEPROM时,工作电流会高达1.5mA,这时需要通过1-Wire总线上的上拉电阻提供强有力的上拉。而在外部电源模式下,DS18B20可以直接通过VDD引脚供电,这种供电方式不需要上拉的MOSFET,且在温度转换期间1-Wire总线可以执行其他动作。另外,当温度超过+100℃时,不推荐使用寄生电源供电方式,因为会有较大的漏电流导致无法正常通信,此时应使用外部供电电源。
64位ROM
64位ROM 和ROM 操作控制部分允许DS18B20 作为一个单线器件工作并遵循单线总线系统一节中所
详述的单线协议直到ROM 操作协议被满足DS18B20 控制部分的功能是不可访问的此协议在ROM
操作中单线总线主机必须首先操作五种ROM 操作命令之一
-
Read ROM(读ROM) [33h]
-
Match ROM(匹配ROM) [55h]
-
Search ROM(搜索ROM) [F0h]
-
Skip ROM(跳过ROM) [CCh]
-
Alarm Search告警搜索 [ECh]
在成功地执行了ROM 操作序列之后DS18B20 特定的功能便可访问然后总线上主机
可提供六个存贮器和控制功能命令之一
存储器
DS18B20的存储器组织结构如图所示。该存储器包含了SRAM暂存寄存器和存储着过温和低温(TH和TL)温度报警寄存器及配置寄存器的非易失性EEPROM。值得注意的是当DS18B20的温度报警功能没有用到的时候,过温和低温(TH和TL)温度报警寄存器可以当做通用功能的存储单元。所有的存储命令在“功能命令”章节有详细描述。
暂存寄存器中的Byte 0和Byte 1分别作为温度寄存器的低字节和高字节。同时这两个字节是只读的。Byte 2和Byte 3作为过温和低温(TH和TL)温度报警寄存器。Byte 4保存着配置寄存器的数据。Byte 5、6、7作为内部使用的字节而保留使用,不可被写入。
暂存寄存器的Byte 8为只读字节,其中存储着该暂存寄存器中Byte 0至Byte 7的循环冗余校验(CRC)值
配置寄存器
用户通过改变表2中R0和R1的值来配置DS18B20的精度。
功能命令
初始化
1-Wire总线上的所有事件都必须以初始化为开始。初始化序列由总线上的主设备发出的复位脉冲以及紧跟着从设备回应的存在脉冲构成。该回应脉冲让总线上的主设备知道在该总线上有从设备(例如DS18B20),并且已经准备好进行操作。
复位脉冲时序图;
//初始化
//10us
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
//1ms
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void ds18b20_reset(void)
{
DS18B20_PORT=0; //拉低DQ
delay_10us(75); //拉低750us
DS18B20_PORT=1; //DQ=1
delay_10us(2); //20US
}
//ds18b20任何操作都需要先进行初始化;
//初始化通过单总线的所有执行操作处理都从一个初始化序列开始。
//初始化序列包括一个 由总线控制器发出的复位脉冲和其后由从机发出的存在脉冲。
//存在脉冲让总线控 制器知道 DS18B20 在总线上且已准备好操作,详见单总线信号节。
/*
主器件首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,
并在随后的480微秒时间内对总线进行检测,
如果有低电平出现说明总线上有DS18B20温度传感器已做出应答。
若无低电平出现一直都是高电平说明总线上无DS18B20温度传感器应答。
做为从器件的DS18B20温度传感器
检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后
等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。
若没有检测到就一直在检测等待。
*/
u8 ds18b20_check(void)
{
u8 time_temp=0;
while(DS18B20_PORT&&time_temp<20) //等待DQ为低电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
else time_temp=0;
while((!DS18B20_PORT)&&time_temp<20) //等待DQ为高电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
return 0;
}
写1和读
对于主机产生写1 时间片的情况数据线必须先被拉至逻辑低电平然后就被释放使数据线
//在写时间片开始之后的15 微秒之内拉至高电平
//对于主机产生写0 时间片的情况数据线必须被拉至逻辑低电平且至少保持低电平60us==
读1
当从DS1820 读数据时主机产生读时间片;当主机把数据线从逻辑高电平拉至低电平时产生读时间片数据线必须保持在低逻辑电平至少1 微秒;来自DS1820 的输出数据在读时间片下降沿之后15 微秒有效;因此为了读出从读时间片开始算起15 微秒的状态;
主机必须停止把I/O 引脚驱动至低电平;在读时间片结束时I/O 引脚经过外部的上拉电阻拉回至高电平;所有读时间片的最短持续期限为60 微秒;各个读时间片之间必须有最短为1微秒的恢复时间
图13指出TINRT,TRC 和TSAMPLE 之和必须小于15us
图14 说明通过使TINRT 和TRC 尽可能小且
把主机采样时间定在15us 期间的末尾系统时序关系就有最大的余地
ROM指令
操作指令 | 指令 | 功能 |
---|---|---|
读ROM | 33h | 该命令在总线上仅有一个从设备时才能使用。该命令使得总线上的主设备不需要搜索ROM命令过程就可以读取从设备的64位ROM编码。当总线上有超过一个从设备时,若再发送该命令,则当所有从设备都会回应时,将会引起数据冲突。 |
匹配ROM | 55h | 该匹配ROM命令之后跟随发送64位的ROM编码使得总线上的主设备能够匹配特定的从设备。只有完全匹配该64位ROM编码的从设备才会响应总线上的主设备发出的功能命令;总线上的其他从设备将会等待下下一个复位脉冲。 |
搜索ROM | F0h | 当系统上电初始化后,主设备必须识别该总线上所有的从设备的ROM编码,这样就可以使得主设备确定总线上的从设备的类型及数量。主设备学习ROM编码是一个清除的过程,则主设备要根据需要循环地发送搜索ROM[F0h]命令(搜索ROM命令跟随着数据交换)来确定总线上所有的从设备。如果仅有一个从设备在该总线上,更加简单的读取ROM命令可以代替搜索ROM的过程。 |
跳过RAM | CCh | 主设备可以使用该命令来同时向总线上的所有从设备发送不要发送任何的ROM编码命令。例如,主设备通过向总线上所有的DS18B20发送跳过ROM命令后再发送温度转换[44h]命令,则所有设备将会同时执行温度转。需要注意的是,当总线上仅有一个从设备时,读取暂存寄存器[BEh]命令后面可以跟随跳过ROM命令。在这种情况下,主设备可以读取从设备中的数据而不发送64位ROM编码。当总线上有多个从设备时,若在跳过ROM命令后再发送读取暂存寄存器命令,则所有的从设备将会同时开始传送数据而导致总线上的数据冲突。 |
告警搜索 | ECh | 该命令的操作与跳过ROM命令基本相同,但是不同的是只有警报标志置位的从设备才会响应。该命令使得主设备确定在最近一次温度转换期间是否有DS18B20有温度报警。当所有的报警搜索命令循环执行后,总线上的主设备必须回到事件序列中的第一步(初始化)。 |
DS18B20功能命令
温度转换[44h]
该命令为初始化单次温度转换。温度转换完后,温度转换的数据存储在暂存寄存器的2个字节长度的温度寄存器中,之后DS18B20恢复到低功耗的闲置状态。如果该设备是采用的“寄生电源”供电模式,在该命令执行10uS(最大)后主设备在温度转换期间必须强制拉高数据线。如果该设备是采用的外部供电模式,主设备在温度转换命令之后可以执行读取数据时序,若DS18B20正在进行温度转换则会响应0电平,温度转换完成则响应1电平。在“寄生电源”供电模式下,因为在整个温度转换期间总线都是强制拉高的状态,故不会有上述响应。
写入暂存寄存器[4Eh]
该命令使得主设备向DS18B20的暂存寄存器写入3个字节的数据。第一个字节的数据写入TH寄存器(暂存寄存器的 Byte 2),第二个字节的数据写入TL寄存器(Byte 3),第三个字节的数据写入配置寄存器(Byte 4)。所有的数据必须是以低位先发的原则。所有的三个字节的数据在写入之前主设备必须先对从设备复位,否则数据将会损坏。
读取暂存寄存器[BEh]
该命令使得主设备可以读取暂存寄存器中存储的值。数据从Byte 0的低位开始传送直到第9个字节(Byte 8 - CRC)读取完毕。主设备若只需要暂存寄存器中的部分数据,则可以在读取数据中通过复位来终止。
拷贝暂存寄存器[48h]
该命令为将暂存寄存器中的TH、TL及配置寄存器(Byte 2,Byte 3和Byte 4)的值拷贝至EEPROM中。如果该设备采用的“寄生电源”供电模式,在该命令发送后10us(最大)内主设备必须强制拉高1-Wire总线超过10ms。
召回EEPROM[B8h]
该命令将温度报警触发值(TH和TL)及配置寄存器的数据从EEPROM中召回至暂存寄存器中的Byte 2,Byte 3和Byte4中。主设备可以在召回EEPROM命令之后执行读取数据时序,若DS18B20正在进行召回EEPROM则会响应0电平,召回EEPROM完成则响应1电平。召回数据操作在上电初始化后会自动执行一次,所以设备在上电期间暂存寄存器中一直会有有效的数据。
读取供电模式[B4h]
主设备通过执行该命令之后再执行读取数据时序来确定总线上的DS18B20是否是由“寄生电源”供电。在读取数据时序中,“寄生电源”供电的DS18B20将会拉低总线,外部电源独立供电模式的DS18B20则会释放总线让其保持在高电平。
读写
读写时序
//普中示例
/*******************************************************************************
* 函 数 名 : ds18b20_reset
* 函数功能 : 复位DS18B20
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds18b20_reset(void)
{
DS18B20_PORT=0; //拉低DQ
delay_10us(75); //拉低750us
DS18B20_PORT=1; //DQ=1
delay_10us(2); //20US
}
/*******************************************************************************
* 函 数 名 : ds18b20_check
* 函数功能 : 检测DS18B20是否存在
* 输 入 : 无
* 输 出 : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 ds18b20_check(void)
{
u8 time_temp=0;
while(DS18B20_PORT&&time_temp<20) //等待DQ为低电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
else time_temp=0;
while((!DS18B20_PORT)&&time_temp<20) //等待DQ为高电平
{
time_temp++;
delay_10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
return 0;
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_bit
* 函数功能 : 从DS18B20读取一个位
* 输 入 : 无
* 输 出 : 1/0
*******************************************************************************/
u8 ds18b20_read_bit(void)
{
u8 dat=0;
DS18B20_PORT=0;
;; //空操作
DS18B20_PORT=1;
;; //该段时间不能过长,必须在15us内读取数据
if(DS18B20_PORT)dat=1; //如果总线上为1则数据dat为1,否则为0
else dat=0;
delay_10us(5);
return dat;
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_byte
* 函数功能 : 从DS18B20读取一个字节
* 输 入 : 无
* 输 出 : 一个字节数据
*******************************************************************************/
u8 ds18b20_read_byte(void)
{
u8 i=0;
u8 dat=0;
u8 temp=0;
for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
{
temp=ds18b20_read_bit();
dat=(temp<<7)|(dat>>1);
}
return dat;
}
/*******************************************************************************
* 函 数 名 : ds18b20_write_byte
* 函数功能 : 写一个字节到DS18B20
* 输 入 : dat:要写入的字节
* 输 出 : 无
*******************************************************************************/
void ds18b20_write_byte(u8 dat)
{
u8 i=0;
u8 temp=0;
for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
{
temp=dat&0x01;//选择低位准备写入
dat>>=1;//将次高位移到低位
//对于主机产生写1 时间片的情况数据线必须先被拉至逻辑低电平然后就被释放使数据线
//在写时间片开始之后的15 微秒之内拉至高电平
//对于主机产生写0 时间片的情况数据线必须被拉至逻辑低电平且至少保持低电平60us
if(temp)
{
DS18B20_PORT=0;
;; //空操作
DS18B20_PORT=1;
delay_10us(6);
}
else
{
DS18B20_PORT=0;
delay_10us(6);
DS18B20_PORT=1;
;; //空操作
}
}
}
/*******************************************************************************
* 函 数 名 : ds18b20_start
* 函数功能 : 开始温度转换
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds18b20_start(void)
{
ds18b20_reset();//复位
ds18b20_check();//检查DS18B20
ds18b20_write_byte(0xcc);//SKIP ROM
ds18b20_write_byte(0x44);//转换命令
}
/*******************************************************************************
* 函 数 名 : ds18b20_init
* 函数功能 : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输 入 : 无
* 输 出 : 1:不存在,0:存在
*******************************************************************************/
u8 ds18b20_init(void)
{
ds18b20_reset();
return ds18b20_check();
}
/*******************************************************************************
* 函 数 名 : ds18b20_read_temperture
* 函数功能 : 从ds18b20得到温度值
* 输 入 : 无
* 输 出 : 温度数据
*******************************************************************************/
double ds18b20_read_temperture(void)
{
double temp;
u8 dath=0;
u8 datl=0;
u16 value=0;
ds18b20_start();//开始转换
ds18b20_reset();//复位
ds18b20_check();
ds18b20_write_byte(0xcc);//SKIP ROM
ds18b20_write_byte(0xbe);//读存储器
datl=ds18b20_read_byte();//低字节
dath=ds18b20_read_byte();//高字节
value=(dath<<8)+datl;//合并为16位数据
if((value&0xf800)==0xf800)//判断符号位,负温度
{
value=(~value)+1; //数据取反再加1
temp=value*(-0.0625);//乘以精度
}
else //正温度
{
temp=value*0.0625;
}
return temp;
}