抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

DS18B20介绍

DS18B20数字温度传感器是DALLAS公司生产的单总线器件,用它来组成一个测温系统具有线路简单,体积小,在一根通信线上可以挂很多这样的数字温度传感器,十分方便。

特点

  1. 通信采用1-Wire接口
  2. n每个DS18B20都有唯一的64位序列码储存在板载ROM中
  3. 无需外部元件
  4. 可从数据线供电,电源范围为3.0V ~ 5.5V。
  5. 可测量的温度范围在-55℃ ~ +125℃
  6. 在-10~+85℃范围内精确度为±0.5℃
  7. 温度计分辨率可设置为9~12位,12位时分辨率对应为0.0625℃

image-20210824153229536

单总线

DS18B20采用1-wire Bus传输数据,所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。

单总线信号类型: 复位脉冲、存在脉冲、写0、写1、读0、读1。

所有这些信号除存在脉冲由DS18B20发出的以外,其他信号都由总线控制器发出。并且,数据传输总是从最低有效位开始。

初始化时序

初始化时序里面包含了复位DS18B20和接收DS18B20返回的存在信号。

主机和DS18B20做任何通讯前都需要对其初始化。

初始化期间:

  1. 总线控制器拉低总线并保持480us以上,挂在总线上的器件将被复位

  2. 释放总线,等到15-60us,此时18B20将返回一个60~240us之间的低电平存在信号

image-20210824154325250

写时序

写时序有2种写法:写0时序和写1时序。总线控制器通过写 1 时序写逻辑 1 到 DS18B20,写 0 时序写逻辑 0 到 DS18B20。

所有写时序必须持续 >=60us,包括:两个写周期之间至少 1us 的恢复时间。当总线控制器把数据线从逻辑高电平拉到低电平的时候,写时序开始。

初始化写时序:

总线控制器要生产一个写时序,必须把数据线拉到低电平然后释放,在写时序开始后的 15us 释放总线。

当总线被释放的时候,5K 的上拉电阻将拉高总线。因此,如果总控制器要生成一个写 0 时序,必须把数据线拉到低电平并持续保持(至少 60us)。

进行写时序:

总线控制器初始化写时序后,DS18B20 在一个 15us 到 60us 的窗口内对 I/O 线采 样。如果线上是高电平,就是写1。如果线上是低电平,就是写0

image-20210824160214829

读时序

  1. 先把总线拉低至少1us
  2. 在15us内选取1us进行读数据
  3. 在拉低的15us(包括上面2点所说的1us)内传输的数据是有效的
  4. 然后总线被释放
  5. 总时间必须>=60us

image-20210824161252256

读1的详细时序:

TINIT,TRC 和 TSAMPLE 之和必须小于 15us

image-20210824162105674

推荐的读1时序:

系统时间可以用下面办法达到最大:

TINIT 和 TRC 保持时间尽可能小;把控制器采样时间放 到 15us 周期的最后。

image-20210824162319244

数据获取

通过单线总线端口访问DS18B20的协议如下:

  1. 初始化

  2. ROM操作指令

  3. DS18B20功能指令、温度转换命令、读取暂存器命令

部分常用ROM指令如下:

image-20210824163430400

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <reg52.h>
#include <intrins.h>
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
/*====================================
自定义类型名
====================================*/
typedef unsigned char INT8U;
typedef unsigned char uchar;

typedef unsigned int INT16U;
typedef unsigned int uint;

/*====================================
硬件接口位声明
====================================*/
sbit DS = P2^2; //DS18B20单总线
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
/*====================================
共阴极数码管段选码
====================================*/
uchar code table[]={
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F - . 关显示
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00
};

/*====================================
数码管位选码
====================================*/
//第1位 2位 3位 4位 5位 6位 7位 8位
uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//数码管位码

/*====================================
函数:void Delay_Ms(INT16U ms)
参数:ms,毫秒延时形参
描述:12T 51单片机自适应主时钟毫秒级延时函数
====================================*/
void Delay_Ms(INT16U ms)
{
INT16U i;
do{
i = MAIN_Fosc / 96000;
while(--i); //96T per loop
}while(--ms);
}
/*us延时函数,执行一次US--所需6.5us进入一次函数需要11.95us*/
void Delay_us(uchar us)
{
while(us--);
}
/*====================================
函数:void Display(INT16U Value)
参数:Value,显示值 取值0-65535
描述:共阴极数码管显示函数可显示一个字节的数
====================================*/
void Display(INT16U Value) //注意由于需要显示的数大于一个字节所有形参需为int型
{
//------------------------------
DU = 0; //关闭段选
P0 = table[Value/100]; //数码管显示百位
DU = 1; //打开段选
DU = 0; //关闭段选

WE = 0; //关闭位选
P0 = T_COM[0]; //第一位数码管
WE = 1; //打开位选
WE = 0; //关闭位选
Delay_Ms(3);
//-------------------------------
DU = 0;
P0 = table[Value%100/10]|0x80; //显示十位
DU = 1;
DU = 0;

WE = 0;
P0 = T_COM[1]; //第二位数码管
WE = 1;
WE = 0;
Delay_Ms(3);
//-------------------------------
DU = 0;
P0 = table[Value%10]; //显示个位
DU = 1;
DU = 0;

WE = 0;
P0 = T_COM[2]; //第三位数码管
WE = 1;
WE = 0;
Delay_Ms(3);
}
/*单总线初始化时序*/
bit ds_init()
{
bit i;
DS = 1;
_nop_();
DS = 0;
Delay_us(75); //拉低总线499.45us 挂接在总线上的18B20将会全部被复位
DS = 1; //释放总线
Delay_us(4); //延时37.95us 等待18B20发回存在信号
i = DS;
Delay_us(20); //141.95us
DS = 1;
_nop_();
return (i);
}
/*写一个字节*/
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生些时序
DS = dat & 0x01;
Delay_us(10);//76.95us
DS = 1; //释放总线准备下一次数据写入
_nop_();
dat >>= 1;
}
}

uchar read_byte()
{
uchar i, j, dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生读时序
DS = 1;
_nop_();//释放总线
j = DS;
Delay_us(10);//76.95us
DS = 1;
_nop_();
dat = (j<<7)|(dat>>1);
}
return (dat);
}
void main()
{
uint i;
uchar L, M;
/* ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x4e);//写暂存器指令
write_byte(0x7f);
write_byte(0xf7);
write_byte(0x1f);//配置工作在9位模式下
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x48);*/
while(1)
{
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x44);//发送温度转换指令
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0xbe);//读取DS18B20暂存器值
L = read_byte();
M = read_byte();
i = M;
i <<= 8;
i |= L;
i = i * 0.0625 * 10 + 0.5;
Display(i);
}
}

评论