这里将我写的STC12C5A60S2单片机控制湿度温度传感DHT11的程序共享一下,是为了让前辈给予斧正。
更新:
2014/06/29 09:01 在结构体DHT11_info中定义了DHT11_CRC,实际上此校验不属于CRC校验,定义名称不合适,
需要修改,这里只做声明,请自行修改
2014/05/31 提供修改方法,适用于不同型号的51单片机(文章最后)
2014/05/27 10:07(DHT11ReadByte(void)函数修改,修改内容已在DHT11.C中Modification部分讲述,为了便于理解修改细节,不涉及功能调试)
2014/04/26 18:04 (重新调试完成)
2014/04/26 17:50 (发现程序有问题,湿度整数部分超过100,重新调试)
2014/04/03 11:25
2014/03/31 15:17
(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)
对于串口调试部分,请参考《单片机程序协助调试方法(一)串口调试》点击进入
实验对象:
实验现象:
测试程序:
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#include <reg52.h> #include "common.h" #include "uart.h" #include "DHT11.h" void main(void) { UB8 i=0; DHT11_info dataCode ; UartInit() ; #if 0 //临时测试DHT11的存在与否 P1=0x00 ;//led if(DHT11Init() <0) //未检测到DHT11 P1=0x01 ; else //检测到DHT11 P1=0x02 ; while(1); #endif while(1) { if(DHT11Init()==DHT11_EXISTENCT) { i=0; /*错误记录:忘记了给i清零,导致前几次测量数据正确,后面的数据都错误(一定要注意)*/ while((DHT11_DATA_BIT )&& (i < 250)) { i++; //临时,具体见调试 /*经过试验,这里250足够大了*/ } /*临时试验,真正试验时必须屏蔽,否则影响后面数据的读取*/ //UartSendString("ready to send data.rn") ; DHT11ReadInfo(&dataCode) ; UartSendValue("Humidity_H : ",dataCode.Humidity_H); UartSendValue("Humidity_L : ",dataCode.Humidity_L); UartSendValue("Temperature_H : ",dataCode.Temperature_H); UartSendValue("Temperature_L : ",dataCode.Temperature_L); UartSendValue("DHT11_CRC : " ,dataCode.DHT11_CRC); UartSendString("rnrn") ; } else { UartSendString("No DHT11 existence.rn"); } } }
/*################DHT11.h start################*/
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#ifndef __DHT11_H__ #define __DHT11_H__ #include "common.h" #include "reg52.h" sbit DHT11_DATA_BIT = P2^0 ;/*根据具体硬件选择*/ typedef struct { UB8 Humidity_H ; UB8 Humidity_L ; UB8 Temperature_H ; UB8 Temperature_L ; UB8 DHT11_CRC; }DHT11_info ; #define DHT11_EXISTENCT 0 /*DHT11存在*/ #define DHT11_NOT_EXISTENCT -1 /*DHT11不存在*/ /*****************外部接口函数******************/ extern SB8 DHT11Init(void) ; extern void DHT11ReadInfo(DHT11_info *temp) ; /**********************************************/ #endif /*__DHT11_H__*/
/*################DHT11.h end################*/
/*################DHT11.C start################*/
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254/*************************************************************************** Module :DHT11.c Purpose :Implementation of DHT11 module. Version :0.01 2014/02/03 12:00(OK) Complier:Keil 8051 C complier V9.01 MCU :STC12C5A60S2 Author :yangrui QQ :279729201 Email :yangrui90s@163.com Modification: ================= 2014/05/17 10:04 Reason: 1.将函数static UB8 DHT11ReadByte(void)内部的 if (DHT11_DATA_BIT) { datCode |= 0x01; } j=0 ; while((DHT11_DATA_BIT) &&(j<250)) ; { j++ ; } 修改为 if (DHT11_DATA_BIT) { datCode |= 0x01; j=0 ; while((DHT11_DATA_BIT) &&(j<250)) ; { j++ ; } } 因为只有当某一bit数据位高电平时,才需要等待电平拉低 (每一bit数据发送之前都是以低电平开始,所以这等待是必须的), 虽然第一种算法没有错误,但是方法二更好理解。 ================= ================= 2014/04/03 11:01 Reason: 1.修改void DHT11ReadInfo(UB8 table[])的入参"UB8 table[]"形式 为DHT11_info *temp,这样的结构更加紧凑。 ================= ================= 2014/03/31 10:48 Reason: 1.在DHT11ReadInfo(UB8 table[])中增加了延时部分,在没有延时的情况下。 发现main函数中有时竟然不发送数据,或者复位后发送一次数据,这是因为 DHT11在采集完数据之后会恢复到空闲状态,如果需要继续采集,需要一个启 动过程。在main函数中添加延时,正常。 但为了安全和方便,直接将延时加载采集数据的函数内部较好。 ================= ***************************************************************************/ #include "DHT11.H" #include <intrins.h> /*外部接口函数在DHT11.H中声明*/ /*****************内部函数******************/ static void delay20msForDHT11(void) ; static void delay10usForDHT11(void) ; static UB8 DHT11ReadByte(void) ; //读取DHT11字节数据 /**********************************************/ /****************************************************** Function :delay20msForDHT11 Input :N/A Output :N/A Return :N/A Description :N/A Note :由STC-ISP V6.67软件针对相应MCU生成,若MCU不同 最好也要修改此函数。 ******************************************************/ static void delay20msForDHT11(void) //@11.0592MHZ { unsigned char i, j, k; i = 1; j = 216; k = 35; do { do { while (--k); } while (--j); } while (--i); } /****************************************************** Function :delay10usForDHT11 Input :N/A Output :N/A Return :N/A Description :N/A Note :由STC-ISP V6.67软件针对相应MCU生成,若MCU不同 最好也要修改此函数。 ******************************************************/ static void delay10usForDHT11(void) { unsigned char i; _nop_(); i = 25; while (--i); } /****************************************************** Function :DHT11Init Input :N/A Output :N/A Return : 0(DHT1 existence) -1(DHT11 not existenct) Description :检测DHT11的存在与否 Note :1.本函数中,等待DHT11的低电平回应结束后才会跳出。 2.为了防止DHT11的未安装或接触不良导致的程序"卡死" 情况的发生,在等待电平转换的同时增加了时间限制, 并且这个时间设置的是较长的,经过试验,在正常连接 DHT11的情况下,还未等到"最后时间的到来",就已经 发生了电平转换,这在大工程中是非常必要的。 ******************************************************/ SB8 DHT11Init(void) { SB8 existenceFlag ; UB8 i=0 ; DHT11_DATA_BIT = HIGH_LEVEL ; _nop_() ; _nop_() ; DHT11_DATA_BIT = LOW_LEVEL ; delay20msForDHT11() ; DHT11_DATA_BIT = HIGH_LEVEL ; delay10usForDHT11() ; delay10usForDHT11() ; delay10usForDHT11() ; delay10usForDHT11() ; delay10usForDHT11() ; if( !DHT11_DATA_BIT) { existenceFlag = DHT11_EXISTENCT ; } else { existenceFlag = DHT11_NOT_EXISTENCT ; } while((!DHT11_DATA_BIT) && (i<250)) { i++ ; //暂时,具体见调试 /*经过调试,这里250足够大了*/ } return existenceFlag ; } /****************************************************** Function :DHT11ReadByte Input :N/A Output :N/A Return :byte-data which is read from DHT11 Description :N/A Note :为了防止DHT11的未安装或接触不良导致的程序"卡死" 情况的发生,在等待电平转换的同时增加了时间限制, 并且这个时间设置的是较长的,经过试验,在正常连接 DHT11的情况下,还未等到"最后时间的到来",就已经 发生了电平转换,这在大工程中是非常必要的。 修改:把if之后的j=0 ,while(){}部分修改到if内部 ******************************************************/ static UB8 DHT11ReadByte(void) { UB8 j=0 ; UB8 i, datCode; for(i=0;i<8;i++) { datCode <<= 1; /*每一bit数据都以50us低电平时隙开始,这里直接等待DHT11把数据线拉到高电平*/ j=0 ; while( (! DHT11_DATA_BIT) && (j<250)) { j++ ; //暂时,具体见调试 /*经过调试,这里250足够大了*/ } delay10usForDHT11() ; delay10usForDHT11() ; delay10usForDHT11() ; delay10usForDHT11() ; if (DHT11_DATA_BIT) { datCode |= 0x01; j=0 ; while((DHT11_DATA_BIT) &&(j<250)) ; { j++ ; //暂时,具体见调试 /*经过调试,这里250足够大了*/ } } } return datCode; } /****************************************************** Function :DHT11ReadInfo Input :N/A Output :DHT11_infor struct Return :N/A Description :读取DHT11采集到的数据 Note :注意增加延时的意义。见"Modification"的 "2014/03/31 10:48"部分。 ******************************************************/ void DHT11ReadInfo(DHT11_info *temp) { temp->Humidity_H = DHT11ReadByte() ; //Humidity_H temp->Humidity_L = DHT11ReadByte() ; //Humidity_L temp->Temperature_H = DHT11ReadByte() ; //Temperature_H temp->Temperature_L = DHT11ReadByte() ; //Temperature_L temp->DHT11_CRC = DHT11ReadByte() ; //DHT11_CRC delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; delay20msForDHT11() ; }
/*################DHT11.C end################*/
补充:common.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifndef __COMMON_H__ #define __COMMON_H__ typedef unsigned char UB8 ; typedef unsigned short int UW16 ; typedef unsigned long UL32 ; typedef char SB8; typedef short int SW16 ; typedef long SL32 ; #define HIGH_LEVEL 1 #define LOW_LEVEL 0 #endif /*__COMMON_H__*/
后期:
1.针对不同的IO:
修改DHT11.h的
1sbit DHT11_DATA_BIT = P2^0 ;/*根据具体硬件选择*/
即可!!
2.针对不同MCU修改:
修改DHT11.c中的static void delay20msForDHT11(void)和static void delay10usForDHT11(void),因为这里的延时函是利用STC-ISP软件自带的工具生成的,是针对STC12C5A60S2的,所以,若用于不同的51单片机,需要修改延时函数,过程截图:
3.对于串口打印:参考http://blog.csdn.net/yagnruinihao/article/details/22662145,这里需要使用11.0592MHZ晶振,直接拷贝uart.h和uart.c,加入工程直接编译即可,如果不同,只需稍作修改。
3.程序的拷贝:
最后
以上就是超级火龙果最近收集整理的关于单片机控制单总线协议湿度温度传感器DHT11之模块化编程(持续更新中)的全部内容,更多相关单片机控制单总线协议湿度温度传感器DHT11之模块化编程(持续更新中)内容请搜索靠谱客的其他文章。
发表评论 取消回复