DS18B20 理解与操作源码
最近研究了DS18B20 数字温度传感器,它的时序控制确实有点小烦躁,参看了很多资料。
其中http://www.cnblogs.com/fengmk2/archive/2007/03/11/670955.html 这篇资料算是很详细的,十分感谢作者的无私奉献。
这里,只是对自己的理解做一个记录。
1
/*
2
程序说明:
3
功能:
4
1、能用上位机控制单片机,具体来说
5
发 握手命令 单片机回状态
6
发 读温度命令 单片机回温度
7
2、接多点温度的情况下,可以通过串口读到任何一个点的温度
8
9
说明:
10
1、ds18b20 都接到p3.7脚
11
2、延时在c程序中确实不好控制,看了网上一些资料,选了一个延时,
12
单位时间大约能做到7.8us的,理论上说通过一定的设置可以满足时序的。
13
14
*/
15![]()
16
#include <reg51.h>
17
#include <intrins.h>
18![]()
19
#define uchar unsigned char
20
#define uint unsigned int
21
sbit ds = P3^7;
22
bit readflag=0;
23![]()
24
//Fuction declaration
25![]()
26
// 串口函数
27
void initCom();
28
void receiveCom();
29
void sendcharCom(uchar);
30![]()
31
//延时函数
32
void delayOne(uint);
33
void temDealy(uint);
34![]()
35
//操作DS18B20函数
36
void dsInit();
37
void dsWait();
38
bit readBit();
39
uchar readByte();
40
void writeByte(uchar);
41
void sendChangeCmd();
42
void sendReadCmd();
43
int getTmpValue();
44![]()
45![]()
46
void main()
47
{
48
uchar tmpValue=0;
49
initCom();
50![]()
51
while (1)
52
{
53
sendChangeCmd();
54
delayOne(1000);
55
tmpValue=getTmpValue();
56
57
if(readflag)
58
{
59
readflag=0;
60
sendcharCom(tmpValue);
61
}
62![]()
63![]()
64
}
65![]()
66![]()
67
}//func main
68![]()
69
//串口初始化
70
void initCom()
71
{
72
TMOD=0X20; //定时器1,工作方式2
73
TH1=0XFD; //9600bps
74
TL1=0XFD;
75
TR1=1; //启动定时器
76
PCON=0X00; //波特率不倍频
77
SCON=0X50; //串口方式1
78
EA=1; //开总中断
79
ES=1; //开串口中断
80
}//func initcom
81![]()
82
//串口中断接受
83
void receiveCom() interrupt 4 using 3
84
{
85
uchar recChar;
86
if(RI)
87
{
88
RI=0;
89
recChar=SBUF;
90
TI=1;
91![]()
92
switch(recChar)
93
{
94
case 0xff:
95
SBUF=0xff;
96
TI=0;
97
break;
98![]()
99
case 0x00:
100
readflag=1;
101
break;
102![]()
103
default:
104
readflag=0;
105
break;
106
}
107
}
108
}//func receivecom
109![]()
110
//串口发送程序
111
void sendCharCom(uchar ch)
112
{
113
SBUF=ch;
114
while(TI==0);
115
TI=0;
116
}//func sendcharcom
117![]()
118![]()
119
//延时1ms
120
void delayOne(uint t)
121
{
122
uint i=0;
123
while(t--)
124
{
125
while(i<125)i++;
126
}
127
}//func delayOneMs
128![]()
129
//一个delay延时约7.8-8us,12Mhz/11.0592Mhz晶振
130
void temDelay(uint i)
131
{
132
while(i>0)i--;
133
}//func temDelay
134![]()
135
//初始化总线上的ds18b20
136
void dsInit()
137
{
138
uint i;
139
uchar etFlag;
140
ds=0;
141
temDelay(80); //延时约600us,符合协议480us的标准
142
ds=1;//拉高总线
143
temDelay(5); //延时约40us,符合30us的标准,等待从机应答信号
144
i++;
145
if (ds==0)
146
etFlag=1; //检测到18b20
147
else
148
etFlag=0; //没有检测到18b20
149
temDelay(20); //延时150us,等待18b20拉低总线
150
ds=1;
151
}//func dsInit
152![]()
153
//读一位数据
154
bit readBit()
155
{
156
uint i;
157
bit bValue; //一位数据
158
ds=0;
159
i++;
160
ds=1; //根据读时序协议先拉低总线,延时8us后再拉高总线
161
//i++;
162
i++;
163
i++; //延时16us,可以读数
164
bValue=ds; //读出一位数据
165
temDelay(10); //延时超过60us,保证读时隙长度
166
return bValue;
167
}//func readBit
168![]()
169
//读一个字节的数据
170
uchar readByte()
171
{
172
uint i;
173
uchar j;
174
uchar btValue; //一个字节数据
175
btValue=0;
176
for(i=0;i<8;i++)
177
{
178
j=readBit();
179
btValue= (j<<7)|(btValue>>1);
180
}
181
return btValue;
182
}//func readByte
183![]()
184
//写一个字节的数据到18b20
185
void writeByte(uchar dat)
186
{
187
uint i;
188
uchar j;
189
bit oneBit;
190
for(j=0;j<8;j++)
191
{
192
oneBit=dat && 0x01;
193
dat=dat>>1;
194
if(oneBit) //写1操作
195
{
196
ds=0;
197
i++;
198
i++; //拉低15us后拉高总线
199
ds=1; //完成写1操作
200
temDelay(10); //延时70us以上,符合协议写1时隙
201
}
202
else //写0操作
203
{
204
ds=0;
205
temDelay(10); //延时70us以上,产生写0时隙,并完成写0操作
206
ds=1;
207
i++;
208
}
209
}
210
}//func writeByte
211![]()
212
//rom操作,发温度转换命令
213
void sendChangeCmd()
214
{
215
dsInit();
216
temDelay(125);
217
writeByte(0xcc); //写skip rom命令
218
writeByte(0x44); //写温度转换命令
219
}//func sendChangeCmd
220![]()
221
//rom操作,发读存储器命令
222
void sendReadCmd()
223
{
224
dsInit();
225
temDelay(125);
226
writeByte(0xcc);
227
writeByte(0xbe); //写读暂存器命令
228
}//func sendReadCmd
229![]()
230
//读温度
231
int getTmpValue()
232
{
233
int tValue;
234
uchar tempLow,tempHigh;
235
sendReadCmd();
236
tempLow=readByte();
237
tempHigh=readByte();
238
tValue=(tempHigh<<8)|tempLow;
239
return tValue;
240
}//func getTmpValue
/*2
程序说明:3
功能: 4
1、能用上位机控制单片机,具体来说5
发 握手命令 单片机回状态6
发 读温度命令 单片机回温度7
2、接多点温度的情况下,可以通过串口读到任何一个点的温度 8
9
说明:10
1、ds18b20 都接到p3.7脚11
2、延时在c程序中确实不好控制,看了网上一些资料,选了一个延时,12
单位时间大约能做到7.8us的,理论上说通过一定的设置可以满足时序的。13
14
*/15

16
#include <reg51.h> 17
#include <intrins.h>18

19
#define uchar unsigned char20
#define uint unsigned int21
sbit ds = P3^7;22
bit readflag=0;23

24
//Fuction declaration25

26
// 串口函数27
void initCom();28
void receiveCom(); 29
void sendcharCom(uchar);30

31
//延时函数32
void delayOne(uint);33
void temDealy(uint);34

35
//操作DS18B20函数36
void dsInit();37
void dsWait();38
bit readBit();39
uchar readByte();40
void writeByte(uchar);41
void sendChangeCmd();42
void sendReadCmd();43
int getTmpValue();44

45

46
void main()47
{48
uchar tmpValue=0; 49
initCom();50

51
while (1) 52
{53
sendChangeCmd();54
delayOne(1000);55
tmpValue=getTmpValue();56
57
if(readflag)58
{59
readflag=0;60
sendcharCom(tmpValue);61
}62

63

64
}65

66

67
}//func main68

69
//串口初始化70
void initCom()71
{72
TMOD=0X20; //定时器1,工作方式2 73
TH1=0XFD; //9600bps 74
TL1=0XFD;75
TR1=1; //启动定时器 76
PCON=0X00; //波特率不倍频 77
SCON=0X50; //串口方式178
EA=1; //开总中断 79
ES=1; //开串口中断 80
}//func initcom81

82
//串口中断接受83
void receiveCom() interrupt 4 using 3 84
{85
uchar recChar;86
if(RI)87
{88
RI=0;89
recChar=SBUF;90
TI=1;91

92
switch(recChar)93
{94
case 0xff:95
SBUF=0xff;96
TI=0;97
break;98

99
case 0x00:100
readflag=1;101
break;102

103
default:104
readflag=0;105
break; 106
} 107
}108
}//func receivecom109

110
//串口发送程序111
void sendCharCom(uchar ch)112
{113
SBUF=ch;114
while(TI==0);115
TI=0;116
}//func sendcharcom117

118

119
//延时1ms120
void delayOne(uint t)121
{122
uint i=0;123
while(t--)124
{125
while(i<125)i++; 126
} 127
}//func delayOneMs128

129
//一个delay延时约7.8-8us,12Mhz/11.0592Mhz晶振130
void temDelay(uint i)131
{132
while(i>0)i--; 133
}//func temDelay134

135
//初始化总线上的ds18b20 136
void dsInit()137
{ 138
uint i;139
uchar etFlag;140
ds=0;141
temDelay(80); //延时约600us,符合协议480us的标准 142
ds=1;//拉高总线143
temDelay(5); //延时约40us,符合30us的标准,等待从机应答信号 144
i++;145
if (ds==0)146
etFlag=1; //检测到18b20 147
else148
etFlag=0; //没有检测到18b20 149
temDelay(20); //延时150us,等待18b20拉低总线150
ds=1;151
}//func dsInit152

153
//读一位数据 154
bit readBit()155
{156
uint i;157
bit bValue; //一位数据 158
ds=0;159
i++;160
ds=1; //根据读时序协议先拉低总线,延时8us后再拉高总线161
//i++; 162
i++; 163
i++; //延时16us,可以读数164
bValue=ds; //读出一位数据 165
temDelay(10); //延时超过60us,保证读时隙长度 166
return bValue;167
}//func readBit 168

169
//读一个字节的数据 170
uchar readByte()171
{172
uint i;173
uchar j;174
uchar btValue; //一个字节数据 175
btValue=0;176
for(i=0;i<8;i++)177
{178
j=readBit();179
btValue= (j<<7)|(btValue>>1);180
}181
return btValue;182
}//func readByte183

184
//写一个字节的数据到18b20185
void writeByte(uchar dat) 186
{187
uint i;188
uchar j;189
bit oneBit;190
for(j=0;j<8;j++)191
{192
oneBit=dat && 0x01;193
dat=dat>>1;194
if(oneBit) //写1操作195
{196
ds=0;197
i++;198
i++; //拉低15us后拉高总线199
ds=1; //完成写1操作200
temDelay(10); //延时70us以上,符合协议写1时隙 201
}202
else //写0操作203
{204
ds=0;205
temDelay(10); //延时70us以上,产生写0时隙,并完成写0操作 206
ds=1; 207
i++;208
}209
}210
}//func writeByte211

212
//rom操作,发温度转换命令 213
void sendChangeCmd() 214
{215
dsInit();216
temDelay(125);217
writeByte(0xcc); //写skip rom命令 218
writeByte(0x44); //写温度转换命令 219
}//func sendChangeCmd220

221
//rom操作,发读存储器命令 222
void sendReadCmd()223
{224
dsInit();225
temDelay(125);226
writeByte(0xcc);227
writeByte(0xbe); //写读暂存器命令 228
}//func sendReadCmd229

230
//读温度 231
int getTmpValue()232
{233
int tValue;234
uchar tempLow,tempHigh;235
sendReadCmd(); 236
tempLow=readByte();237
tempHigh=readByte();238
tValue=(tempHigh<<8)|tempLow;239
return tValue;240
}//func getTmpValue


浙公网安备 33010602011771号