DHT11温湿度.docx
《DHT11温湿度.docx》由会员分享,可在线阅读,更多相关《DHT11温湿度.docx(19页珍藏版)》请在冰豆网上搜索。
DHT11温湿度
DHT11温湿度传感器
参数:
相对湿度:
分辨率:
0.1%RH 16Bit
精度:
25℃ 正负 %2
温度:
分辨率:
0.1%RH 16Bit
量程范围:
25℃ 正负0.2℃至 -40℃ ~-80℃
响应时间:
1/e(63%) 10S
电气特性:
供电DC3.5 -5.5V 电流 0.3mA 待机60uA
采样周期:
每次大于2秒
引脚说明
1、VDD 供电 3.5V-5.5VDC
2、DATA 串行数据,单总线,必须接上拉电阻 5.1K左右,这样空闲时 DATA总是为高电平
3、GND 接地,电源负极
4、NC 空脚
描述:
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。
它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。
传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能 8 位单片机相连接。
电路图:
引脚图
DHT11是通过单总线与微处理器通讯,只需要一根线,一次传送40位数据,高位先出。
数据格式:
8bit湿度整数数据 +8bit湿度小数数据 +8bint温度整数数据 +8bit温度小数数据 +8bit校验位
校验算法:
将湿度、温度的整数小数累加,只保留低8位。
微处理器(M0)与DHT11通信约定:
主从结构,DHT11为从机,M0作为主机,只有主机呼叫从机,从机才能应答。
详细流程:
M0发送起始信号->DHT响应信号->DHT通知M0准备接受信号->DHT发送准备好的数据->DHT结束信号->DHT内部重测环境温湿度数据并记录数据等待下一次M0的起始信号。
由流程可知,每一次M0获取的数据总是DHT上一次采集的数据,要想得到实时的数据,连续两次获取即可,官方不建议连续多次读取DHT,每次读取的间隔时间5秒就足够获取到准确的数据,上电时DHT需要1S的时间稳定。
M0起始信号:
1、设置DATA引脚为输出状态并输出高电平
2、再将DATA输出为低电平,持续时间大于18ms,此时DHT检测到后从低功耗模式->高速模式
3、DATA引脚设置为输入状态,由于上拉电阻的关系,DATA就变为高电平,从而完成一次起始信号。
C语言程序
1.voidstart()//开始信号
2.
3.{
4.
5. io=1;
6.
7. delay1();
8.
9. io=0;
10.
11. delay(25);//主机把总线拉低必须大于18ms保证DHT11能检测到起始信号
12.
13. io=1; //发送开始信号结束后拉高电平延时20-40us
14.
15. delay1();//以下三个延时函数差不多为24us符合要求
16.
17. delay1();
18.
19. delay1();
20.
21.}
DHT响应信号、准备信号:
(DHT在M0DATA引脚输出低电平时,从低功耗模式转至高速模式,等待DATA引脚变为高电平)
1、DHT输出80us低电平作为应答信号
2、DHT输出 80us高电平通知微处理器准备接受数据
3、连续发送 40位数据(上次采集的数据)
1.if(!
io)//判断从机是否有低电平响应信号//
2.
3. {
4. while(!
io);//判断从机发出80us的低电平响应信号是否结束//
5.
6. while(io);//判断从机发出80us的高电平是否结束如结束则主机进入数据接收状态
7.
8. R_H=receive_byte();//湿度高位
9.
10. R_L=receive_byte();//湿度低位
11.
12. T_H=receive_byte();//温度高位
13.
14. T_L=receive_byte();//温度低位
15.
16. check=receive_byte();//校验位
17.
18. io=0;//当最后一bit数据接完毕后从机拉低电平50us//
19.
20. for(i=0;i<7;i++)//差不多50us的延时
21.
22. delay1();
23.
24. io=1;//总线由上拉电阻拉高进入空闲状态
25.
26. num_check=R_H+R_L+T_H+T_L;
27.
28. if(num_check==check)//判断读到的四个数据之和是否与校验位相同
29.
30. {
31.
32. RH=R_H;
33.
34. RL=R_L;
35.
36. TH=T_H;
37.
38. TL=T_L;
39.
40. check=num_check;
41.
42. }
43.
44. }
45.
46.}
DHT数据信号:
数据为“0”格式:
50us的低电平 +26-28us的高电平
数据为“1”格式:
50us的低电平 +70us的高电平
1.ucharreceive_byte()//接收一个字节//
2.
3.{
4.
5. uchari,temp;
6.
7. for(i=0;i<8;i++)//接收8bit的数据
8.
9. {
10.
11. while(!
io);//等待50us的低电平开始信号结束
12.
13. delay1();//开始信号结束之后延时26us-28us以下三个延时函数
14.
15. delay1();
16.
17. delay1();
18.
19. temp=0;//时间为26us-28us表示接收的为数据'0'
20.
21. if(io==1)
22.
23. temp=1;//如果26us-28us之后还为高电平则表示接收的数据为'1'
24.
25. while(io);//等待数据信号高电平'0'为26us-28us'1'为70us
26.
27. data_byte<<=1;//接收的数据为高位在前右移
28.
29. data_byte|=temp;
30.
31. }
32.
33. returndata_byte;
34.
35.}
DHT结束信号:
DHT的DATA引脚输出40位数据后,继续输出低电平50us后转为输入状态,由于上拉电阻,DATA随之变为高电平。
DHT内部开始重测环境温湿度数据,并记录数据,等待外部的起始信号。
完整程序
1.#include
2.#include
3.typedefunsignedcharBYTE;
4.typedefunsignedintWORD;
5.#defineuintunsignedint
6.#defineucharunsignedchar
7.sbitio=P1^0;//dht11data端接单片机的P1^0口//
8.
9.sbitrw=P0^6;//一下三行是设置lcd1602的使能端//
10.
11.sbitrs=P0^7;
12.
13.sbitep=P0^5;
14.
15.typedefbitBOOL;//此声明一个布尔型变量即真或假//
16.
17.uchardata_byte;
18.
19.ucharRH,RL,TH,TL;
20.
21.
22.
23.//***************延时函数*************************************
24.
25.voiddelay(ucharms)//延时模块//
26.
27.{
28.
29. uchari;
30.
31. while(ms--)
32.
33.
34.
35.for(i=0;i<100;i++);
36.
37.}
38.
39.
40.voiddelay1()//一个for循环大概需要8个多机器周期一个机器周期为1us晶振为12MHz也就是说本函数延时8us多此延时函数必须德稍微精确一点
41.
42.{
43.
44. uchari;
45.
46. for(i=0;i<1;i++);
47.
48.}
49.
50.
51.
52.//***************************************************************
53.
54.//lcd模块//
55.
56.BOOLlcd_bz()//测试lcd忙碌状态返回值为布尔型数值真或假'1'.'0'
57.
58.{
59.
60.BOOLresult;
61. rs=0; //读忙信号
62. rw=1;
63. ep=1;
64. _nop_();
65. _nop_();
66. _nop_();
67. _nop_();
68. result=(BOOL)(P2&0x80);
69. ep=0;
70. result;
71.
72.}
73.
74.voidwrite_cmd(ucharcmd)//写指令//
75.
76.{
77.
78. while(lcd_bz());
79. rs=0;
80. rw=0;
81. ep=0;
82. _nop_();
83. _nop_();
84. P2=cmd;
85. _nop_();
86. _nop_();
87. _nop_();
88. _nop_();
89. ep=1;
90. _nop_();
91. _nop_();
92. _nop_();
93. _nop_();
94. ep=0;
95.
96.}
97.
98.
99.
100.voidwrite_addr(ucharaddr)//写地址//
101.
102.{
103.
104. write_cmd(addr|0x80);//LCD第一行的首地址为0x80第二行的首地址为0x80+0x40=0xc0
105.
106.}
107.
108.
109.
110.voidwrite_byte(uchardat)//写字节//
111.
112.{
113.
114. while(lcd_bz());
115. rs=1;
116. rw=0;
117. ep=0;
118. _nop_();
119. _nop_();
120. P2=dat;
121. _nop_();
122. _nop_();
123. _nop_();
124. _nop_();
125. ep=1;
126. _nop_();
127. _nop_();
128. _nop_();
129. _nop_();
130. ep=0;
131.
132.}
133.
134.
135.
136.voidlcd_init()//lcd初始化//
137.
138.{
139.
140. write_cmd(0x38);//设置LCD两行显示一个数据由5*7点阵表示,数据由8跟线传输
141.
142. delay
(1);
143.
144. write_cmd(0x0c);//清除屏幕显示
145.
146. delay
(1);
147.
148. write_cmd(0x06);//设定输入方式增量不移位
149.
150. delay
(1);
151.
152. write_cmd(0x01);//开整体显示关光标不闪烁
153.
154. delay
(1);
155.
156.}
157.
158.
159.
160.voiddisplay(ucharaddr,ucharq)//在某一地址上显示内容adder表示的是地址偏移量q表示显示的字符或数字//
161.
162.{
163.
164. delay(10); write_addr(addr);
165.
166. write_byte(q);
167.
168. delay
(1);//修改此时间可以改变LCD上数值跳变的数度
169.
170.}
171.
172.
173.
174.//**************************dht11测试某块*************************************//
175.
176.voidstart()//开始信号
177.
178.{
179.
180. io=1;
181.
182. delay1();
183.
184. io=0;
185.
186. delay(25);//主机把总线拉低必须大于18ms保证DHT11能检测到起始信号
187.
188. io=1; //发送开始信号结束后拉高电平延时20-40us
189.
190. delay1();//以下三个延时函数差不多为24us符合要求
191.
192. delay1();
193.
194. delay1();
195.
196.}
197.
198.
199.
200.ucharreceive_byte()//接收一个字节//
201.
202.{
203.
204. uchari,temp;
205.
206. for(i=0;i<8;i++)//接收8bit的数据
207.
208. {
209.
210. while(!
io);//等待50us的低电平开始信号结束
211.
212. delay1();//开始信号结束之后延时26us-28us以下三个延时函数
213.
214. delay1();
215.
216. delay1();
217.
218. temp=0;//时间为26us-28us表示接收的为数据'0'
219.
220. if(io==1)
221.
222. temp=1;//如果26us-28us之后还为高电平则表示接收的数据为'1'
223.
224. while(io);//等待数据信号高电平'0'为26us-28us'1'为70us
225.
226. data_byte<<=1;//接收的数据为高位在前右移
227.
228. data_byte|=temp;
229.
230. }
231.
232. returndata_byte;
233.
234.}
235.
236.
237.
238.voidreceive()//接收数据//
239.
240.{
241.
242. ucharT_H,T_L,R_H,R_L,check,num_check,i;
243.
244. start();//开始信号//
245.
246. io=1; //主机设为输入判断从机DHT11响应信号
247.
248. if(!
io)//判断从机是否有低电平响应信号//
249.
250. {
251. while(!
io);//判断从机发出80us的低电平响应信号是否结束//
252.
253. while(io);//判断从机发出80us的高电平是否结束如结束则主机进入数据接收状态
254.
255. R_H=receive_byte();//湿度高位
256.
257. R_L=receive_byte();//湿度低位
258.
259. T_H=receive_byte();//温度高位
260.
261. T_L=receive_byte();//温度低位
262.
263. check=receive_byte();//校验位
264.
265. io=0;//当最后一bit数据接完毕后从机拉低电平50us//
266.
267. for(i=0;i<7;i++)//差不多50us的延时
268.
269. delay1();
270.
271. io=1;//总线由上拉电阻拉高进入空闲状态
272.
273. num_check=R_H+R_L+T_H+T_L;
274.
275. if(num_check==check)//判断读到的四个数据之和是否与校验位相同
276.
277. {
278.
279. RH=R_H;
280.
281. RL=R_L;
282.
283. TH=T_H;
284.
285. TL=T_L;
286.
287. check=num_check;
288.
289. }
290.
291. }
292.
293.}
294.
295.//*****************************************************************************
296.
297.
298.
299.voidmain()//主函数模块//
300.
301.{
302.
303. lcd_init();//初始化LCD
304.
305. while
(1)
306.
307. {
308.
309. receive();//接收数据
310.
311.display(0x00,'R');//LCD的第一行显示
312.
313.display(0x01,':
');
314.
315.display(0x02,RH/10+0x30);//0x30表示带字库的LCD1602中0x30的位置放有数字0RH/10+0x30即表示湿度的十位数字在字库RH/10+0x30的位置处放着
316.
317.display(0x03,RH%10+0x30);
318.
319.display(0X04,'%');
320.
321.display(0x40,'T');//LCD的第二行显示
322.
323.display(0x41,':
');
324.
325.display(0x42,TH/10+0x30);
326.
327.display(0x43,TH%10+0x30);
328.
329.display(0x44,0xdf);//以下两个是温度单位的处理
330.
331.display(0x45,0x43);
332.
333. }
334.}