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
21sbit ds = P3^7;
22bit readflag=0;
23
24//Fuction declaration
25
26// 串口函数
27void initCom();
28void receiveCom();
29void sendcharCom(uchar);
30
31//延时函数
32void delayOne(uint);
33void temDealy(uint);
34
35//操作DS18B20函数
36void dsInit();
37void dsWait();
38bit readBit();
39uchar readByte();
40void writeByte(uchar);
41void sendChangeCmd();
42void sendReadCmd();
43int getTmpValue();
44
45
46void 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//串口初始化
70void 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//串口中断接受
83void 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//串口发送程序
111void sendCharCom(uchar ch)
112{
113 SBUF=ch;
114 while(TI==0);
115 TI=0;
116}//func sendcharcom
117
118
119//延时1ms
120void 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晶振
130void temDelay(uint i)
131{
132 while(i>0)i--;
133}//func temDelay
134
135//初始化总线上的ds18b20
136void 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//读一位数据
154bit 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//读一个字节的数据
170uchar 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
185void 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操作,发温度转换命令
213void sendChangeCmd()
214{
215 dsInit();
216 temDelay(125);
217 writeByte(0xcc); //写skip rom命令
218 writeByte(0x44); //写温度转换命令
219}//func sendChangeCmd
220
221//rom操作,发读存储器命令
222void sendReadCmd()
223{
224 dsInit();
225 temDelay(125);
226 writeByte(0xcc);
227 writeByte(0xbe); //写读暂存器命令
228}//func sendReadCmd
229
230//读温度
231int 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 char
20#define uint unsigned int
21sbit ds = P3^7;
22bit readflag=0;
23
24//Fuction declaration
25
26// 串口函数
27void initCom();
28void receiveCom();
29void sendcharCom(uchar);
30
31//延时函数
32void delayOne(uint);
33void temDealy(uint);
34
35//操作DS18B20函数
36void dsInit();
37void dsWait();
38bit readBit();
39uchar readByte();
40void writeByte(uchar);
41void sendChangeCmd();
42void sendReadCmd();
43int getTmpValue();
44
45
46void 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//串口初始化
70void 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//串口中断接受
83void 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//串口发送程序
111void sendCharCom(uchar ch)
112{
113 SBUF=ch;
114 while(TI==0);
115 TI=0;
116}//func sendcharcom
117
118
119//延时1ms
120void 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晶振
130void temDelay(uint i)
131{
132 while(i>0)i--;
133}//func temDelay
134
135//初始化总线上的ds18b20
136void 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//读一位数据
154bit 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//读一个字节的数据
170uchar 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
185void 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操作,发温度转换命令
213void sendChangeCmd()
214{
215 dsInit();
216 temDelay(125);
217 writeByte(0xcc); //写skip rom命令
218 writeByte(0x44); //写温度转换命令
219}//func sendChangeCmd
220
221//rom操作,发读存储器命令
222void sendReadCmd()
223{
224 dsInit();
225 temDelay(125);
226 writeByte(0xcc);
227 writeByte(0xbe); //写读暂存器命令
228}//func sendReadCmd
229
230//读温度
231int 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