前言5 D2 {4 p+ b( r8 Q6 @6 t
了解DHT11温湿度传感器相关知识,进行DHT11传感器的开发及数据获取,并通过串口调试助手查看* b9 o, Z2 D! S9 K+ V+ `
( Y% E) J+ {6 f. x4 S6 Q* _
一、温湿度传感器相关知识4 z6 X2 s% n$ {! T( s$ \; Q/ Y: K
1. DHT11简介/ \5 f, }6 i& }7 F; T
DHT11温湿度传感器是一种比较便宜的常见的温湿度传感器,它的内部由两个元件构成,一个是电阻式的感湿元件用来检测环境湿度,另一个是NTC测温元件来测量温度,在测得数据后,两个元件会将数据传送给内部一个集成的8位的处理器来对数据进行处理,并将它们转换为数字量,这些数据可以通过串口传送给主机。DHT11温湿度传感器有四个管脚,只有一条是数据线接口,所以在传输数据时仅需要1个I/O就能同时传输测得的温度以及湿度,在进行程序编写时更加简洁方便。因为DHT11集成度较好,体积比较小,所以消耗也很小,抗干扰能力更强,稳定性较好,不易受到外界干扰。0 ]6 q B8 k2 b# K1 h% R) w
7 t+ B0 r* f% ^" \6 v2 X! L0 h1 k7 A
Pin1 VDD 供电 3-5.5V DC4 y$ _; I" O' G+ Y+ L/ T$ R, M
Pin2 DATA 串行数据,单总线, X3 s* q3 i' n6 t, n, G0 U$ _' S
Pin3 NC 空脚,悬空1 D" ?: |. F5 t9 [' i
Pin4 GND 接地,电源负极
6 c* t, z: R. d b( e" V5 A) E$ a% L7 z4 O0 l3 n4 S
DHT11集成度很高,封装的很简洁,只有四个管脚,所以连接也是相对比较方便。DHT11管脚Pin1接一个3-5.5V的直流电源的正极,管脚Pin2为数据端,主要用于传输数据,但是在接线时需要加一个5KΩ的上拉电阻连接到主机MCU上,用来保证数据传输的稳定性,同时还要注意这个5KΩ是在管脚Pin2与主机之间的接线小于20m时才有用,在大于20m时就需要根据实际情况来确定需要加多大的上拉电阻来保持稳定性。管脚Pin3不起什么作用,只需要将其悬空不接线即可,管脚Pin4接地。4 {( J+ W) ?. T- E8 |
7 ], g6 O$ s( g# N$ ]* y( d9 s5 Y2 F" k
2.数据格式
3 b; x3 D/ x# }. ?* @: qDHT11和DS18B20不同,DHT11不需要配置,可以直接读取数据,一次完整的数据传输为40bit,先传输高字节的数据再传输低字节的数据,也就是低位后出,高位先出模式。% d; ^9 j0 r4 h% z
数据格式: 8bit湿度整数数据 + 8bit湿度小数数据
5 O. f1 h/ r9 j. c' l0 w+8bit温度整数数据 + 8bit温度小数数据
9 q; l& G/ p) T/ K; {: \2 x+8bit校验和
1 d3 o$ o! R; Z: f' @; P数据传送正确时校验和数据等于
3 s/ x- ]3 @* x9 d' o* o8bit湿度整数数据 + 8bit湿度小数数据, t: c3 n. a- }! D
+8bit温度整数数据 + 8bit温度小数数据
* c1 s5 U; U6 f0 q所得结果的末8位。0 x i9 @8 C0 d. ]9 p" F! k
& j% o6 ]9 B4 K1 y4 M9 s4 P
! r! K$ O& r8 s2 q% ^9 E5 ^3.数据传输
0 l5 G# X, f" O5 K0 |- v0 E数据线一开始处于高电平状态,用户MCU将总线电平拉低,表示用户要开始获取数据,然后将电平拉高并延时等待一段时间,等待DHT11回复,如果DHT11将总线拉低,表示已经收到主机信号,并响应主机信号,准备输出,然后将总线电平拉高,并延时一段时间,表示准备传输40bit的数据。然后将数据总线拉低一段时间开始传输数据,主要是进行2进制数据传输,传输0和1,并用不同的拉高电平延时时间来表示数据0和1。用户可以选择读取湿度还是温度,整数还是小数。并且数据传输是需要DHT11收到主机MCU发送的开始信号,才会开始采集数据传输数据,而且此时DHT11会转到低速模式。
7 I* D' w3 B1 K+ ^/ j; w- P7 A& w5 V6 w
. k3 F) _# s% _( v+ S
- {4 H# O: Y( [9 Q3 u X- J# J9 n总线在空闲时因为上拉电阻会处于高电平状态,主机用户MCU会发送信号将电平拉低至少18us,太短DHT11可能会检测不到主机的起始信号。之后主机会再将电平拉高20-40us,DHT11识别到后,会将电平拉低80us,表示DHT11已经接收到主机发送的开始信号,之后再将总线切换到输入模式,然后DHT11会再将电平拉高80us表示竹北开始传输数据。之后会再将电平拉低,然后开始传输数据。
3 @! U; p+ c j) a
1 i' o; B* ?, o8 \# _* {当接收到主机的开始信号后,DHT11会将总线拉低80us来发送响应信号,表示已经接收到,然后会将总线拉高80us,并准备发送数据,每一位的数据都以50us的低电平间隙开始,就是每两个数据之间都有一个50us的低电平信号来表示一位数据传输完成。DHT11用电平拉高延时的时间来表示数据为位0还是1。通常用拉高26-28us来表示数据‘0’,用拉高70us来表示数据‘1’。当最后一位数据传输完成后,DHT11会将总线拉低50us,随后总线又会因为上拉电阻将总线拉高,并处于空闲状态。
% p* X3 E2 R9 L5 M; Y& m) w! I$ P* ^; n7 ?, C) O4 x
DHT11读取数据“0”时序图
1 J% ^9 S8 ~- W3 y
. J5 B+ m0 B& E. [# P) a* P# Q$ R
! ^$ g1 l6 D' j9 e4 Q' Q( m: O
; o' f* [ w% gDHT11读数据“1”时序图' \. n( A6 }; B2 U
?) M2 |4 R- i9 _0 H2 T7 L
! e( }+ R! `3 x% z2 \# n+ ]9 O& @9 m- ~- P. B& K) x) B* v6 L2 x! p
m U. g3 X; E) V9 ^6 X9 S二、程序实现
' E! }( v1 j- `0 D/ z1.dht11.h3 X6 Z6 ^: a9 v4 f: q: x8 e
DHT11的程序实现主要是根据它的读写时序来实现的,因此在进行程序的编写时要根据它的读写时序进行模拟,实现单片机与DHT11之间的数据通信。5 P7 ]8 x# G" m8 ~" I7 H: S* C, q" H
: i/ S" u/ W, J8 \8 q7 e$ r( ]; |
代码如下(示例):! i y; z/ o& b4 {9 g1 s7 ^; b. H' Y
- #ifndef __DHT11_H/ b% q$ V9 }1 }$ b4 Y4 m
- #define __DHT11_H# D! Z! I7 ~# i
8 W" y' ]! P, q* i! Z( o- #include "stm32f10x.h"; } b: O# b! h; s' G1 u* m: D/ f' I
, n1 M0 o7 q, _' L9 L" }; W! \- typedef struct
4 I0 r6 ~( x' R, m- q( z+ Z# V - {, R: S/ g$ g0 D
- uint8_t humi_int; //湿度的整数部分5 @6 P5 n* N6 b, l6 S9 e: q6 I) R9 P
- uint8_t humi_deci; //湿度的小数部分9 g# g: x/ {2 w. C6 q% l. C4 H. y
- uint8_t temp_int; //温度的整数部分2 ?4 Y! Q# A0 g8 o* o; r. G
- uint8_t temp_deci; //温度的小数部分
' l1 l& o& _( x$ ^1 |! P - uint8_t check_sum; //校验和5 Y' [( j6 v& l) R6 ~) }# ?* c' q
-
2 Z6 `3 c6 |# `$ O) ^ - } DHT11_Data_TypeDef;
* i! ` Y! {- [3 }3 x
6 b" a( Z! h5 {3 o- " E0 y- m4 r8 w
- ! A2 f) X8 |1 ^1 B4 w
- /************************** DHT11 连接引脚定义********************************/' ~6 t" z7 R9 R/ }, _/ l
- #define DHT11_Dout_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd9 `4 I( {* j' v' v7 @' a/ Z, i
- #define DHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOE
$ y3 X) a/ \9 @ - ( s+ M8 T0 _5 D% U( f% `/ i. ] z
- #define DHT11_Dout_GPIO_PORT GPIOE
) |* w, |& Z2 ~3 e1 W, v - #define DHT11_Dout_GPIO_PIN GPIO_Pin_6+ {0 H0 [7 e$ Q2 s$ G
, d, x/ o% z; S& x2 g
. E. ?9 R) @$ R4 V: Y- 8 [2 g! v& m) N5 `( X5 |
- /************************** DHT11 函数宏定义********************************/" `/ ?" Z3 x4 s5 q. f- R0 u
- #define DHT11_Dout_0 GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
3 v* W+ C$ P6 X - #define DHT11_Dout_1 GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) ( [# [2 V2 \7 G% M* n( U
- ) [# F9 m6 n* q6 g
- #define DHT11_Dout_IN() GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) " _ `2 I( B! Y( g, q" ?+ b% q
; a/ G, f) z/ R8 E5 I$ B& g5 R" q) M- , ]9 p* p* J) Q- ?" c. N. C
+ L6 g& O& `0 v) l- /************************** DHT11 函数声明 ********************************/ J! Z3 s: W$ j8 x7 k4 z
- void DHT11_Init ( void );
3 S+ Y8 ?( H% n/ d6 L- P( k% Q - uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data );
' G5 e9 g* U4 H
& `) D* i$ F2 V1 Z- #endif
u" X9 c. P* L" [& l- a! _
复制代码 % z" O& Y1 M' G- z! R
DHT11用到的数据总线是PE6,接线时,DHT11数据线接到PE6,以及我们需要用到的函数的声明:- f. {& a3 x! b7 t- L* n
Void DHT11_Init(void)为DHT11的初始化函数;
1 n( v8 l$ l! h; V$ F5 I( Z8 P' y2 Z- k Nuint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data )为DHT11的数据读取函数,这个函数会将读取到的数据赋值给DHT11_Data结构体里的变量,然后还会有一个返回值判断是否读取成功;( _1 J& V% R* T( q
! Y# w. N$ h1 W2.dht11.c
) g' u5 G( O* g" n) X) H2 Y- ]代码如下(示例):! N$ e2 k. l1 u Y. F0 n* V
- #include "dht11.h"
4 O; C: T l( Q! E - #include "delay.h"1 `! z) M1 W- d# ~4 r" E% ?
% [8 t# \- M1 W; y- static void DHT11_GPIO_Config ( void );
+ t" `: R" R1 o3 S5 v' S - static void DHT11_Mode_IPU ( void );" W L# h4 {3 x4 j5 ^9 f4 A: f
- static void DHT11_Mode_Out_PP ( void );4 d) W# ~ |5 ?. a) \* [
- static uint8_t DHT11_ReadByte ( void );
( v3 V7 u* J4 O! h" [' X+ |
+ v y( x Q7 X5 m' @8 j& j$ `& V
7 `% f8 U h$ g1 T- z7 }- E- /**
1 ]: N& u9 c4 R) _ - * @brief DHT11 初始化函数3 Q) }- H( d+ m* Z2 ]; t6 U
- * @param 无+ O5 H* d; U2 ^, }' b# H7 o, z7 M
- * @retval 无
8 h' I; u% h7 e0 q& Z - */
1 q* [9 R6 x. f7 V" J/ c - void DHT11_Init ( void )
( n2 |" c: T/ s Y/ x3 m# `# C; F - {
4 ^7 {5 a1 c2 F, X5 t! D5 ` - DHT11_GPIO_Config ();3 X& f' {; D7 U8 e1 I [
-
# Q! d0 P% X1 V" g' k1 V - DHT11_Dout_1; // 拉高GPIOB10
- M2 Q& i! I; `& s, [ - }
, g; e, L0 W& F, L1 l
4 E: O$ n; d9 V3 e! M6 Y: y0 T- /*! F* e# Y' J9 Z+ m' x
- * 函数名:DHT11_GPIO_Config
, C' F" [; R2 I2 z/ x( ` - * 描述 :配置DHT11用到的I/O口
' K2 L9 E5 ~7 O3 k5 S9 c7 @2 E - * 输入 :无" J" u% T; @5 [0 _( M
- * 输出 :无
6 p0 ?7 H- r4 i. n - */
0 P* K' w' ^* N+ y - static void DHT11_GPIO_Config ( void )
3 \ @( o z/ V - {
$ f& l2 i+ ^' p( `( } - /*定义一个GPIO_InitTypeDef类型的结构体*/4 ~2 r5 m- E, I6 w3 a
- GPIO_InitTypeDef GPIO_InitStructure;
1 P6 F( W, _0 J3 [
/ M- g w3 W4 `. U$ X3 ]-
0 I, k2 x$ f. Y$ b9 W - /*开启DHT11_Dout_GPIO_PORT的外设时钟*/
0 u3 g, y* C1 r, ^* O - DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );
4 o- [- E5 \+ N8 v9 Q -
4 T8 ^+ x) h1 S5 z; t. m- w - /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ 5 z+ r- G( g* R- M
- GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
; a; M7 M! v' a" h0 e# e' J
9 ^4 M/ P, ^! b* E# F( V' N7 |- /*设置引脚模式为通用推挽输出*/2 G/ R6 w5 \2 H! C1 z+ R
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
; `; [ ` `" \) P# t& d
3 T5 h, l( H: f" h% n, W8 l- /*设置引脚速率为50MHz */
& ^/ c a) \8 C4 [2 _- j3 P - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; j6 |# c3 J: L, k* D5 q6 A
- " V4 v0 p' u t/ y
- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
9 v- V+ Z$ y0 t - GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure ); & x. x" a" A. p0 L
-
* h5 _. N1 N! A$ g, d$ R - }
% B: n+ r& s' b# L( U8 o, D
/ k [8 {) N5 M, O# q- /*9 g$ n. J# ]2 U3 ^5 |6 X
- * 函数名:DHT11_Mode_IPU e% U; u3 \' ~1 e! a
- * 描述 :使DHT11-DATA引脚变为上拉输入模式" J$ f, V! S: @
- * 输入 :无
9 B) `3 Y" [8 r- q+ X - * 输出 :无% \, ^# \8 b0 c
- */
+ v* ]$ ^4 A$ I5 y' L - static void DHT11_Mode_IPU(void)
. ]: n: A5 c& ^$ ^ - {* A1 h) e( _1 C$ X
- GPIO_InitTypeDef GPIO_InitStructure;2 e8 ^7 G" j! f0 n1 n3 _
- U- v+ H& o3 d0 `- ?0 ^- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
2 q9 U8 Y) F5 e3 Z9 K - GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
" @+ e) o% f1 L* { - 2 G- \5 B2 y+ `4 U2 ~5 F n9 X' z
- /*设置引脚模式为浮空输入模式*/ 9 S& M+ I" ?) T- [; M1 \
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; & E( Q% b( Y' h& A9 s( l+ y% l
- 4 O2 ~- V. m7 `! o. P* C
- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
: C( e1 T' e% _! H2 ~2 B - GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
: O. ^# f, c4 d, e. [7 X - 7 h2 ]; Z; }) p
- }2 a! R- B9 s, l( c, q0 \
- 2 s P# l4 f( c( k
- /*
- C+ z# M& _3 U; j4 q- B1 }2 j% u$ u - * 函数名:DHT11_Mode_Out_PP* W/ _7 a8 N& z$ X8 W7 f
- * 描述 :使DHT11-DATA引脚变为推挽输出模式
1 r& s) g( p, Q- c/ ^ - * 输入 :无1 M8 x8 z9 u1 H6 T# e5 u/ l
- * 输出 :无0 o8 o4 ?3 c* Q0 d3 U6 U
- */; }: W& N( n s9 K+ {: n# Z' G
- static void DHT11_Mode_Out_PP(void)
* ~7 h, O1 N, p8 {- S3 X - {. g+ I( S1 I% A5 _6 U# @9 `0 W
- GPIO_InitTypeDef GPIO_InitStructure;
) Y" E ~- `. r( L3 ?% O- K+ B - + v, d4 b! d6 u+ @' D
- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
1 O$ I {( t* k$ X) ~2 B - GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN; 0 I* s2 r/ v8 r' Q7 O
- 5 i& b, y: l, o9 I1 ^
- /*设置引脚模式为通用推挽输出*/
8 l; f: q/ ?/ A2 u8 W' T) x6 W - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
" t0 g. @9 c( R8 u- b9 L! J1 o2 Z - 8 E K6 Y& t& `, D$ e
- /*设置引脚速率为50MHz */ 6 Q" K6 X4 P" ^% X# u4 `
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
4 H( o |/ C [7 Q
2 X8 c/ B; m0 T" j- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/) j0 V+ N! I9 P1 y$ c/ `2 y, R2 ]
- GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
4 m/ E- Z+ ]; F" P9 o& j -
5 k0 r8 `* j8 ~- d+ u/ K' L - }3 G" E9 |) F1 o4 m5 t# \& S
+ f: |: F) B9 J; s- /* 3 W# M- h# V$ k, O
- * 从DHT11读取一个字节,MSB先行* K; x( Z1 K! r
- */
- K; _0 t& E( o5 x - static uint8_t DHT11_ReadByte ( void )
8 @- ~+ Y* r5 w3 W - {2 g( F5 R; _3 v! h/ j s
- uint8_t i, temp=0;
2 G; a6 Q9 _1 l$ a6 u" C+ `! R; m# S - 1 Z" P+ X% q0 V! D8 z6 r9 o8 \5 K
& l4 x6 z, C. s2 S' J% j2 f/ B- for(i=0;i<8;i++)
& P* h) l- n) \2 }: _ - { : f& i5 K2 W# M3 s5 E0 c7 q
- /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ : i' r; D! R+ t! }6 s0 Q# K& c
- while(DHT11_Dout_IN()==Bit_RESET);
8 ~8 x% [) x5 b2 N1 Q
' U2 W! U4 u# D. |9 a" `1 {$ t- /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,/ R. o: s% }* F# K& N) l1 }+ n( s
- *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
8 d$ V `* R1 z2 S3 w - */3 \2 u3 U7 R( g' i4 [
- delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可
: k, Y: A- c6 d( g. `1 i: S# J) T! p9 f
1 u* i2 _1 I9 V. x- if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */4 I/ M( C0 w0 ?% @% ^9 I
- {
/ j/ d; M% d( [ - /* 等待数据1的高电平结束 */, A& ~, {: f+ x' k
- while(DHT11_Dout_IN()==Bit_SET);
5 x0 }2 G/ \! {+ c - # l8 o( V2 e4 P$ [0 a
- temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行
& ^0 t6 ?! \3 ]- f& u- G - }$ I, ~1 u$ z" V0 X2 i h
- else // x us后为低电平表示数据“0”
. N+ n/ K" a/ A+ x - {
j% ^, Z* L9 ~3 K6 ~% ] - temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行2 F9 r A: q" M- ~: v
- }% V: p8 E# |8 x; I6 ^! c: G0 p/ D1 S
- }
: f8 C* x' c) x- q -
* C' c# ~2 p, c1 J# n4 I x4 H - return temp;
/ B4 ^1 ^! N8 Y2 A' B - 6 r! q3 _; P+ d
- }
( O( U1 s$ c( K& D
$ Q/ J, s; S5 C0 ~3 {4 _- 0 h: ?- ^" w" I P T
- /* E2 @! Z! o3 [
- * 一次完整的数据传输为40bit,高位先出/ }( Z2 G- ~) m" E$ F/ U1 i8 D
- * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
! M- x) S2 r( R7 t/ ] - */
$ r) e1 K, o. V3 a2 v - uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)$ M* ]+ t% m5 A- v! F
- { - t4 u4 ?9 Z( Z8 o+ g
- /*输出模式*/
# [, x% Y! O9 e) v# m+ Z - DHT11_Mode_Out_PP();
, Q% Y- E3 a# P: L0 g; D7 C7 u# _2 N - /*主机拉低*/0 R! Z7 J' ~/ l) H. \
- DHT11_Dout_0;" N2 O+ _6 D* d4 C/ j
- /*延时18ms*/
$ B' M& c" n+ h* C; m - delay_ms(18);
a! c. G2 O M# `& _8 D# _/ K& _* o
' K" K) z/ T R! ?" M5 z$ n- /*总线拉高 主机延时30us*/
3 T( Z0 ]( K1 J/ j) J7 `1 | - DHT11_Dout_1; # f& j; T0 R. w: A
- ) u& W! A' O! L* H* d
- delay_us(30); //延时30us
- a0 W2 |' C+ I
! k$ b+ ]" ^ Q- L- /*主机设为输入 判断从机响应信号*/
9 W" a& M1 }0 W7 C& j2 b$ U) ]' `( t - DHT11_Mode_IPU();( U5 b! Y/ Q0 o; c5 p8 N. Z
: B# ]7 K6 _* r t, K- /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ " X7 m& D6 T' b7 r: T- v/ i) A
- if(DHT11_Dout_IN()==Bit_RESET) 3 {4 Y& N1 y! v, W8 F
- {
# o0 x& M: ~1 f# y1 l - /*轮询直到从机发出 的80us 低电平 响应信号结束*/ 1 Q0 U, g6 ^$ i
- while(DHT11_Dout_IN()==Bit_RESET);
1 ]6 ~0 i% q" u% X% s! T! u - + b) S) @0 A, h- ^) q$ @2 d
- /*轮询直到从机发出的 80us 高电平 标置信号结束*/
& D, a+ L$ F. i - while(DHT11_Dout_IN()==Bit_SET);
/ H7 i& M) v5 y$ A
# f0 g: D2 N. e) U$ |- /*开始接收数据*/ 7 d4 j) {& _0 E
- DHT11_Data->humi_int= DHT11_ReadByte();
" J5 U/ Z7 L/ v9 }- f" ? - 2 Y+ T g6 j6 f0 D
- DHT11_Data->humi_deci= DHT11_ReadByte();+ c9 g! w0 }6 Q) p
- 7 E2 h. @' ?4 k6 [! G4 h. z. b
- DHT11_Data->temp_int= DHT11_ReadByte();
* Z# _# @3 p. [8 G7 G - ( C1 |: w1 o2 N
- DHT11_Data->temp_deci= DHT11_ReadByte();$ \( e( z3 Q8 e9 F3 c$ j- U/ E
- & I( y- Y. X' c: \4 N# u
- DHT11_Data->check_sum= DHT11_ReadByte();: M% ?. K& L$ @( d; w) t2 w
8 t, w6 p! }2 |+ ?# L4 _- ( \: Q$ ^8 e$ T( [5 K4 w( s
- /*读取结束,引脚改为输出模式*/
- z5 ], X5 H1 m! o - DHT11_Mode_Out_PP();
, x6 F X% y- a - /*主机拉高*/* O- o& y t- O
- DHT11_Dout_1;
" Y' b& j* X/ B/ w# I9 N2 [+ N - 1 `# ^$ b e' F0 D8 N
- /*检查读取的数据是否正确*/! A/ t) V% E: C$ s0 q2 s
- if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)$ ?; O7 W+ N$ k: f5 e
- return SUCCESS;$ y& D1 `, @- O& u9 J) d a) I
- else / H+ ^9 s D( f+ K+ Z
- return ERROR;
% y& W& [% K/ d7 G: R6 [% i - }- X2 ~4 u1 E3 R( s* y/ H1 y3 E
-
! g B' c& n1 T8 \: g& f& U! L - else" o5 b! n U x
- return ERROR;
# C& l; `& G0 X: P -
3 p* O0 f; {! [/ R5 T7 a3 g - }
9 V; i; @ ]/ K1 y% b) t - 0 a& a$ g* s; Z% K" w# K1 r
1 k# g' N7 f# E1 |
复制代码 8 t T' D1 Z [" w2 Y$ X8 [
3.main.c
$ f) [# Z) | A( `- #include "stm32f10x.h"9 P) Z7 ?+ L2 c* f/ Q& S
- #include "delay.h"
2 u0 D8 w# E- l9 o |6 _+ o - #include "usart.h") n- `5 g( D: e% z/ U
- #include "dht11.h"
9 x& l8 X6 u' f5 P
( d; s2 R% H0 j- int main()# S8 \, h1 B- S0 I4 k% ^3 n& y
- {
! K% `' ^! ?; ~1 Q - DHT11_Data_TypeDef Dht_Data;# z' T# Z- B1 H1 M0 a3 j* S
- char Temp_Str[ 10 ] = { 0 };8 w; H2 q. \. {% z0 r
- char Hum_Str[ 10 ] = { 0 };
1 P- q8 E9 P6 V8 [8 [* D - USART_Config(); //初始化串口
5 U. d: o, j! ^' K) A - SysTick_Init(); //初始化系统定时器: R- I3 W6 g0 y6 k
- printf("\r\n***Dht11 温湿度传感器实验***\r\n");* E$ [ }1 M( _, p* n
- DHT11_Init(); //初始化DTT11的引脚
5 D- k# z$ Q- J - while(1)
! m9 O3 P7 _6 b' R7 s8 _ - {
/ W5 \1 x% A) b. w( c! B - //调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息* L6 N5 v/ a% G' y4 M! r8 G
+ B3 a0 L- W8 ]5 N- if(DHT11_Read_TempAndHumidity(&Dht_Data) == SUCCESS)1 i9 S4 u, ^2 @% l5 D, x
- {" J+ | e# P! n2 n! L" c' R1 W
- sprintf(Temp_Str,"%d.%d",Dht_Data.temp_int,Dht_Data.temp_deci);# |; [" ~; w2 W, G
- sprintf(Hum_Str,"%d,%d",Dht_Data.humi_int,Dht_Data.humi_deci);" @% z! K y! a4 S* r f
- printf("温度数据为:%d.%d ℃\r\n",Dht_Data.temp_int,Dht_Data.temp_deci);! H: [6 q- a& o8 q2 t2 B
- printf("湿度数据为:%d.%d %RH\r\n",Dht_Data.humi_int,Dht_Data.humi_deci);
) V7 g" B4 x. I% r - }
5 r( i- n) x+ G, ^6 A+ S - else
/ b1 k& P9 o- t" d2 D) u: {' | - printf("error\r\n");
! F$ T Q: S8 x, l" l - " r% ~. x; A$ C+ q% G0 ~- a
; m& w+ V$ C( v. q H- delay_ms(2000);
$ t6 }5 _0 t& |. @ - }
( C8 v; L. R! @; K& `6 m: k - }, S' P) ?5 |( s9 H$ H" j, \& d
复制代码 . m' O' J2 L5 e$ e' x! \
; S& w `# H% S0 B1 n' ^: t4.串口显示
" g% M+ v/ u; Q' o将开发板连接电脑,然后打开串口调试助手,就会看到温度以及湿度的数据$ }5 ]" m. X0 K7 S3 x
3 |4 ~- j3 r+ S* n, n! V( S( _0 {9 v8 ]9 i
# n/ ^7 s$ w1 S* G; w
/ R l2 Y% l5 N+ ]$ q% W* [+ b8 {
* R7 a4 s J" ?" u
总结3 w" a/ S% B- B
做到这一步算是已经完成温湿度采集并串口显示,有需要的话可以进行LCD显示。
& N8 s$ q& L# l% |( H————————————————9 u* r7 C U* T% j& K7 {( Q0 q; T9 P
版权声明:清道 夫
8 b( R& ]0 W# e
# R- I# K+ Z; ~5 F0 y6 Z$ J) a* U% ^, N% s
|