2、DS18B20内部结构
DS18B20内部结构主要由四部分组 成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
3、温度传感器(这个我也不大清楚)
下图是温度测量电路
测温原理:用一个高温度系数的振荡器确定一个门周期,内部计数器在这个门周期内对一个低温度系数的振荡器的脉冲进行计数来得到温度值。计数器被预置到对应于-55摄氏度的一个值。如果计数器在门周期结束前到达0,则温度寄存器(同样初始化到-55摄氏度)的值增加,表明所测温度大于-55摄氏度。
(1。温度系数振荡器是指一种振荡器,它的振荡频率与温度之间有一个特定的关系,即不同的温度对应不同的振荡频率。反之,测量出振荡器的输出频率,就可测量出温度值。
2.高温度系数振荡器:它的振荡频率受温度的影响很大,温度稍有变化,频率就会变化很多,即对温度敏感,多用于温度传感器。
3.低温度系数振荡器:它的振荡频率受温度的影响很小,即使温度变化很大,它的频率也基本不变。
)
同时,计数器被复位到一个值,这个值由斜坡式累加器电路确定,斜坡式累加器电路用来补偿感温振
荡器的抛物线特性。然后计数器又开始计数直到 0,如果门周期仍未结束,将重复这一过程。
斜坡式累加器用来补偿感温振荡器的非线性,以期在测温时获得比较高的分辨力。这是通过改变计数
器对温度每增加一度所需计数的的值来实现的。因此,要想获得所需的分辨力,必须同时知道在给定温度
下计数器的值和每一度的计数值。
4、DS18B20温度寄存器
对于12位来说,第12为符号位,剩下11位为温度,由于测量温度范围为-55到125,则只顺7位整数,其它4位为小数,
于是两个寄存器的内容分别是:
高字节的寄存器的高5位为符号,低3位与低字节的高4位为温度的整数部分,低4位为小数部分。
注意:温度是以补码方式存放的
5、64 位(激)光刻 ROM组成
最前面 8 位是单线系列编码(DS1820 的编码是19h)。
下面 48 位是一个唯一的序列号。最后 8 位是以上 56 位的 CRC 码。
单线总线控制器必须
得天独厚提供 5 个ROM操作命令其中之一:1) Read ROM,2)Match ROM,3)Search Rom,4)Skip ROM,5)Alarm Search。成功进行一次 ROM 操作后,就可以对 DS1820 进行特定的操作,总线控制器可以发
出六个存储器和控制操作命令中的任一个。
6、存储器
DS18B20的存储器包括高速暂存器RAM和可电擦除RAM,可电擦除RAM又包括温度触发 器TH和TL,以及一个配置寄存器。存储器能完整的确定一线端口的通讯,数字开始用写寄存器的命令写进寄存器,接着也可以用读寄存器的命令来确认这些数
字。当确认以后就可以用复制寄存器的命令来将这些数字转移到可电擦除RAM中。当修改过寄存器中的数时,这个过程能确保数字的完整性。
高速暂存器RAM是由8个字节的存储器组成;第一和第二个字节是温度的显示位。第三和第四个字
节是复制TH和TL,同时第三和第四个字节的数字可以更新;第五个字节是复制配置寄存器,同时第五个字节的数字可以更新;六、七、八三个字节是计算机自身
使用。用读寄存器的命令能读出第九个字节,这个字节是对前面的八个字节进行校验。
7、测量温度
通过单线总线端口访问 DS18B20 的协议如下:
? 初始化
? ROM 操作命令
? 存储器操作命令
? 执行/数据
a、初始化
通过单线总线的所有执行(处理)都从一个初始化序列开始。初始化序列包括一个由总线控制器发出
的复位脉冲和跟有其后由从机发出的存在脉冲。
b、ROM 操作命令
Read ROM [33h]
这个命令允许总线控制器读到 DS1820 的8 位系列编码、唯一的序列号和 8 位CRC 码。只有在总线上存
在单只 DS1820 的时候才能使用这个命令。如果总上有不止一个从机,当所有从机试图同时传送信号时就会
发生数据冲突(漏极开路连在一起开成相与的效果)。
Match ROM [55h]
匹配 ROM 命令,后跟 64位 ROM 序列,让总线控制器在多点总线上定位一只特定的 DS1820。只有和 64
位 ROM 序列完全匹配的 DS1820 才能响应随后的存储器操作命令。所有和 64 位ROM 序列不匹配的从机都将
等待复位脉冲。这条命令在总线上有单个或多个器件时都可以使用。
Skip ROM [CCh]
这条命令允许总线控制器不用提供 64 位ROM 编码就使用存储器操作命令,在单点总线情况下右以节省
时间。如果总线上不止一个从机,在 Skip ROM命令之后跟着发一条读命令,由于多个从机同时传送信号,
总线上就会发生数据冲突(漏极开路下拉效果相当于相与)。
Search ROM [F0h]
当一个系统初次启动时,总线控制器可能并不知道单线总线上有多少器件或它们的 64 位 ROM编码。搜
索 ROM 命令允许总线控制器用排除法识别总线上的所有从机的 64 位编码。
Alarm Search [ECh]
这条命令的流程图和 Search ROM 相同。 然而, 只有在最近一次测温后遇到符合报警条件的情况, DS1820
才会响应这条命令。报警条件定义为温度高于 TH 或低于TL。只要 DS1820 不掉电,报警状态将一直保持,
直到再一次测得的温度值达不到报警条件。
c、存储器操作
7、写时间隙
当主机总线 t o 时刻从高拉至低电平时 就产生写时间隙 见图 2 25 3 图 2 25
4 从 to 时刻开始 15us 之内应将所需写的位送到总线上 DSl820 在 t 后15-60us间对总线
采样 若低电平 写入的位是 0 。若高电平 写入的位是 1
连续写 2 位间的间隙应大于 1us
8、读时间隙
主机总线 to 时刻从高拉至低电平时 总线只须保持低电平 l 7ts 之后
在 t1 时刻将总线拉高 产生读时间隙 读时间隙在 t1 时刻后 t2 时刻前有效 t2距 to 为15
us 也就是说 t2时刻前主机必须完成读位 并在 t o 后的60us到120us 内释放总线读位子程序(读得的位到 C 中)
10、总结
单个DS18B20测温系统步骤:
初始化
跳过序列号
启动温度转换
初始化跳过序列号
读9个寄存器,前两个为温度
附:个人实验:
DS18B20的DQ接P37口,共阳数码管的位为P23--P27,段为P0口
/********************************************
名称:DS18B20
功能:测温度系统,测量范围为-55.00到99.99摄氏度
作者:littlebird100
时间:2009-9-12
*********************************************/
#include<REG52.h>
#include"mydelay_10us.c"
#include"mydisplay.c"
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^7;
extern void reset();
extern uint readtmp();
void main()
{
uint Tmp;
uchar LED[4]={0,0,0,0};
uchar POINT[4]={0x00,0x80,0x80,0x80};
while(1)
{
display(LED,POINT); //显示
Tmp=readtmp(); //取温度
LED[3]=Tmp%10; //取个位
Tmp/=10;
LED[2]=Tmp%10; //取十位
Tmp/=10;
LED[1]=Tmp%10; //取百位
LED[0]=Tmp/10; //取千位
}
}
/******************复位********************/
void reset()
{ uchar flag=0;
DQ=1;
delay_10us(1);
DQ=0;
delay_10us(70); //至少延时22us
DQ=1;
delay_10us(8);
flag=DQ;
delay_10us(15);
}
/****************读一字节*********************/
uchar readbyte()
{
uchar i,outdata=0;
for(i=0;i<8;i++)
{
DQ=1;
delay_10us(1);
DQ=0;
outdata>>=1; //必须在15us内读取
DQ=1;
if(DQ)
outdata|=0x80;
delay_10us(4);
}
return(outdata);
}
/*****************写一字节********************/
void writebyte(uchar indata)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=1;
delay_10us(1);
DQ=0;
DQ=indata&0x01; //必须在15us内写入
delay_10us(5);
DQ=1;
indata>>=1;
}
delay_10us(4);
}
/****************读温度***********************/
uint readtmp()
{
uint tmp;
uchar tl,th,temp,temp1;
reset();
writebyte(0xcc); // 跳过序列号
writebyte(0x44); // 启动温度转换
reset();
writebyte(0xCC);
writebyte(0xBE); //读9个寄存器,前两个为温度
tl=readbyte(); //低位
th=readbyte(); //高位
temp=tl&0x0f; //取低四位
temp=temp*6.25; //小数部分
tl>>=4;
th<<=4;
temp1=tl|th; //整数部分
tmp=temp1*100+temp; //四位数,高两位为整数,低两位为小数
return (tmp);
}
/**************************************************************
名称:mydisplay
功能:显示子程序,两个参数,第一个是显示的数,第二个是小数点,0x00--表示有小数点,0x80---表示无小数点(point[0]表示第二个数的小数点,point[1]表示时钟点,point[2]表示第三个数的小数点,point[3]表示第四个数的小数点)
作者:littlebird100
时间:2009-9-12
**************************************************************/
#ifndef __mydisplay_c__
#define __mydisplay_c__
#include<REG52.h>
#include"mydelay_10us.c"
void display(unsigned char *LED,unsigned char *point)
{
unsigned char i;
unsigned char Table[16]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x27,0x21,0x06,0x0e};
unsigned char Scan[5]={0x70,0xb0,0xd0,0xe0,0xf0};
for(i=0;i<4;i++)
{
P0=Table[LED
]|point;
P2=Scan;
delay_10us(100);
P2=Scan[4]; //关闭LED
}
}
#endif
/******************10us延时*****************************
名称: delay_10us
功能: 延时10us
作者: littlebird100
1---27us
2---37us
3---45us
4---56us
5---66us
6---76us
7---86us
10--115us
100---1ms
*******************************************************/
#ifndef __mytime_c__
#define __mytime_c__
void delay_10us(unsigned int time)
{
while(time--);
}
#endif
用户1404628 2009-12-26 12:06
用户194501 2009-9-14 15:42
用户188034 2009-9-13 23:06
用户405381 2009-9-13 19:30
用户194501 2009-9-13 13:54
用户188034 2009-9-13 09:46