前言" V9 ?7 [( @$ s0 R
了解DHT11温湿度传感器相关知识,进行DHT11传感器的开发及数据获取,并通过串口调试助手查看" ~/ ^, w) R: G7 P
# E( c6 h, D l9 I, }
一、温湿度传感器相关知识8 q7 Y3 r( y. F `
1. DHT11简介
* H: O+ a+ _2 ]; B0 t* f" zDHT11温湿度传感器是一种比较便宜的常见的温湿度传感器,它的内部由两个元件构成,一个是电阻式的感湿元件用来检测环境湿度,另一个是NTC测温元件来测量温度,在测得数据后,两个元件会将数据传送给内部一个集成的8位的处理器来对数据进行处理,并将它们转换为数字量,这些数据可以通过串口传送给主机。DHT11温湿度传感器有四个管脚,只有一条是数据线接口,所以在传输数据时仅需要1个I/O就能同时传输测得的温度以及湿度,在进行程序编写时更加简洁方便。因为DHT11集成度较好,体积比较小,所以消耗也很小,抗干扰能力更强,稳定性较好,不易受到外界干扰。( ~: c( h1 H# B6 x
( s; n; Q5 q1 g- s
Pin1 VDD 供电 3-5.5V DC3 s3 o; l. Z9 a# ^ y1 e+ f
Pin2 DATA 串行数据,单总线 n& Z6 y b% h2 t
Pin3 NC 空脚,悬空. N# q1 R# D2 ?8 }
Pin4 GND 接地,电源负极* O! G4 r G5 r" p# p. Y
1 n) o2 A, O% t! x$ Y
DHT11集成度很高,封装的很简洁,只有四个管脚,所以连接也是相对比较方便。DHT11管脚Pin1接一个3-5.5V的直流电源的正极,管脚Pin2为数据端,主要用于传输数据,但是在接线时需要加一个5KΩ的上拉电阻连接到主机MCU上,用来保证数据传输的稳定性,同时还要注意这个5KΩ是在管脚Pin2与主机之间的接线小于20m时才有用,在大于20m时就需要根据实际情况来确定需要加多大的上拉电阻来保持稳定性。管脚Pin3不起什么作用,只需要将其悬空不接线即可,管脚Pin4接地。0 W3 w; k0 D( V- W- ?8 b
8 `, f( G1 j' |+ f- n, t1 L8 b1 n0 O# t+ `# T2 E2 s
2.数据格式
! Y; O- J9 [3 w6 _8 sDHT11和DS18B20不同,DHT11不需要配置,可以直接读取数据,一次完整的数据传输为40bit,先传输高字节的数据再传输低字节的数据,也就是低位后出,高位先出模式。* `- [2 S$ S0 B5 j
数据格式: 8bit湿度整数数据 + 8bit湿度小数数据. a, ]0 c8 ?0 ? e) ^
+8bit温度整数数据 + 8bit温度小数数据& _. ~' j( |; n8 W8 e
+8bit校验和
( w: X! v! T5 Q& U数据传送正确时校验和数据等于. Q/ d7 B; }9 P
8bit湿度整数数据 + 8bit湿度小数数据- \1 ^# i; U4 Y( m/ r9 a- U
+8bit温度整数数据 + 8bit温度小数数据& m: Z4 b, ^- g' H6 b. f
所得结果的末8位。1 X6 q3 }9 n+ Q( K5 c
# n$ f2 v) A; ~* @8 h v+ V y+ c; w3 W' `
3.数据传输. P6 D @. B+ d; B/ {
数据线一开始处于高电平状态,用户MCU将总线电平拉低,表示用户要开始获取数据,然后将电平拉高并延时等待一段时间,等待DHT11回复,如果DHT11将总线拉低,表示已经收到主机信号,并响应主机信号,准备输出,然后将总线电平拉高,并延时一段时间,表示准备传输40bit的数据。然后将数据总线拉低一段时间开始传输数据,主要是进行2进制数据传输,传输0和1,并用不同的拉高电平延时时间来表示数据0和1。用户可以选择读取湿度还是温度,整数还是小数。并且数据传输是需要DHT11收到主机MCU发送的开始信号,才会开始采集数据传输数据,而且此时DHT11会转到低速模式。6 B) V9 r+ @1 d9 n( k7 Q
- L' x6 w. ] O
, d. D, e, }: i/ v, K; L
8 u. i% ^$ s. p+ ]
总线在空闲时因为上拉电阻会处于高电平状态,主机用户MCU会发送信号将电平拉低至少18us,太短DHT11可能会检测不到主机的起始信号。之后主机会再将电平拉高20-40us,DHT11识别到后,会将电平拉低80us,表示DHT11已经接收到主机发送的开始信号,之后再将总线切换到输入模式,然后DHT11会再将电平拉高80us表示竹北开始传输数据。之后会再将电平拉低,然后开始传输数据。
2 F, Q3 h1 l, q
$ T) H, m5 k. K- F' i, G当接收到主机的开始信号后,DHT11会将总线拉低80us来发送响应信号,表示已经接收到,然后会将总线拉高80us,并准备发送数据,每一位的数据都以50us的低电平间隙开始,就是每两个数据之间都有一个50us的低电平信号来表示一位数据传输完成。DHT11用电平拉高延时的时间来表示数据为位0还是1。通常用拉高26-28us来表示数据‘0’,用拉高70us来表示数据‘1’。当最后一位数据传输完成后,DHT11会将总线拉低50us,随后总线又会因为上拉电阻将总线拉高,并处于空闲状态。
7 c1 ^- f4 P4 V4 g# e; ]" O
" Q( D6 R5 x: B3 a! U( ]DHT11读取数据“0”时序图
) r6 ?: E; F+ l: k5 p
$ d" e' ]; l- q$ }' [% ?( ?; K
# c3 S, t9 z( i4 ^- H
& h& k3 b" b! Y( o: l5 j; P2 W
DHT11读数据“1”时序图. J" t* Q" G9 V6 j+ x' |
. ?% z0 g& J4 r9 S* h$ r* o# A1 R
( f+ w4 x8 S% Q6 Y+ @. {
+ Z' ]2 E8 _0 W; P
" v/ `+ D% {/ m2 y
二、程序实现
3 c/ }2 X. }% s3 u- b2 X, m. M7 t+ B1.dht11.h1 A, }) b+ U& y9 u/ y/ M6 t* r9 P* h; b
DHT11的程序实现主要是根据它的读写时序来实现的,因此在进行程序的编写时要根据它的读写时序进行模拟,实现单片机与DHT11之间的数据通信。
: c# d" W: M% D1 B* Z4 L v, M7 L- ^1 I" h
, L, z% S6 q5 O代码如下(示例):
. u0 f3 }2 H; s8 l( P- #ifndef __DHT11_H- J& H( ]" h7 {5 F+ x3 E- Z4 }3 ]. {
- #define __DHT11_H1 u1 ?' O$ V- {/ O* P+ N
- 9 q5 s9 M/ ~! J7 U: }
- #include "stm32f10x.h"
/ T9 w2 p- k) c6 s! M0 |% s
, U& C' f9 p m1 E4 a8 }- typedef struct9 i% f6 R u$ N1 B* }
- {9 q/ ]) O. ]% S& d/ c. E( r* L
- uint8_t humi_int; //湿度的整数部分0 X* I: \" k4 ?
- uint8_t humi_deci; //湿度的小数部分& U4 F3 O3 c( n0 Q! e
- uint8_t temp_int; //温度的整数部分8 X# k0 h+ | ?' h/ E% U3 N' P! T
- uint8_t temp_deci; //温度的小数部分
" @/ u1 f( B" N( ~) \1 H" { - uint8_t check_sum; //校验和9 o3 `1 v8 L) \- i, c$ `0 o
- 5 u$ `, {1 \% t h0 M: I9 L, \
- } DHT11_Data_TypeDef;
4 R( N9 g4 u) g0 \& q - 8 }2 s! V, j: D2 E
3 @% _6 J9 P0 L4 x( \
) g, a A5 X; b! `- /************************** DHT11 连接引脚定义********************************/* d5 N: b2 E' n) T
- #define DHT11_Dout_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd( W1 X0 J1 r! D; o9 c! p# W
- #define DHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOE
6 k6 t+ ~6 z7 K# X+ q1 e - 1 B. o: G) S& T" k
- #define DHT11_Dout_GPIO_PORT GPIOE r4 n4 ?7 {1 y" @
- #define DHT11_Dout_GPIO_PIN GPIO_Pin_6. ^' ?! [" n( c' E7 d7 M; G7 ]
- 6 J; X4 G$ H" S' b Q' ]( R
' A8 |( V+ i: ^( W( A5 y
- X# y/ w' ]+ \4 x# V, m5 Z0 h9 \6 _- /************************** DHT11 函数宏定义********************************/
" ~6 r# U, |# p7 t6 l# F - #define DHT11_Dout_0 GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
- P, c( B& V+ e$ m/ g+ h - #define DHT11_Dout_1 GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) 9 q% Y1 s' {, @" m
) A& s z1 @! Q% l1 p, U- #define DHT11_Dout_IN() GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
2 Y- e! ?, c* Y' U" u; t- N - 3 n8 S! t9 N6 i6 j" K
- / c0 q0 T/ G8 V' L/ Q2 j( l
- Y$ E0 o. k8 L! m% \
- /************************** DHT11 函数声明 ********************************/( R: g3 ~6 P/ r/ W% ~/ j- ?
- void DHT11_Init ( void );
6 ~; \, r+ ~0 ^ - uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data );
6 K9 Y/ F% {- U" }2 [, W7 z! S - / x: G+ E( e& L: x0 j# k
- #endif, O/ D- P! U% X+ d0 l2 B# [
复制代码 , _$ ?* _% ]7 V) R4 `' K
DHT11用到的数据总线是PE6,接线时,DHT11数据线接到PE6,以及我们需要用到的函数的声明:& Y2 r2 V( x9 N) e: T3 X& l+ |. s
Void DHT11_Init(void)为DHT11的初始化函数;
* }8 F4 Q& p* L' |7 L$ Muint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data )为DHT11的数据读取函数,这个函数会将读取到的数据赋值给DHT11_Data结构体里的变量,然后还会有一个返回值判断是否读取成功;( T2 ]9 d. p# B# S2 `3 T
1 n8 _5 r7 j4 S- c' b2.dht11.c, u5 ?6 {! t* d1 c% B. z- w
代码如下(示例):3 T' h; w0 k& j! Z$ e5 ~
- #include "dht11.h"
1 D; t$ r% a$ @8 [! |/ U - #include "delay.h"$ M5 [* R1 S1 F$ z/ ]: y7 @! A
- 3 z' r" V* V+ d8 `
- static void DHT11_GPIO_Config ( void );+ ~4 C3 c- K5 c% y' S! x! [ ]
- static void DHT11_Mode_IPU ( void );
) {, o/ M4 D* |. e' Z - static void DHT11_Mode_Out_PP ( void );: h" i! z+ c4 [$ R. p
- static uint8_t DHT11_ReadByte ( void );! m- H0 _7 ]2 i# u6 p
- % k4 ^. A3 f1 l) T
+ R! o' Q" x. y6 v- /**& e$ ~! {- X8 m. |9 k4 k
- * @brief DHT11 初始化函数0 u: a' o; u1 m% {; v
- * @param 无
5 @5 V2 T/ O6 U8 [. Y - * @retval 无+ m$ {3 @2 Z) ^: y
- */
6 [5 y! l @, ?6 f& { - void DHT11_Init ( void )
8 i# i8 G8 v6 R! \4 R- @8 N% B& B - {
7 k* L2 X# ^, C0 F7 w8 G0 V7 q - DHT11_GPIO_Config ();
1 f2 Y' C; t/ i1 B: ` - $ m( } |3 Y: H# V
- DHT11_Dout_1; // 拉高GPIOB10: k; p8 p8 a% d3 o, q1 a4 D8 o2 x3 O
- }2 h" t( e$ c: Z4 z& k; R
- $ n: b2 y; l# ^/ s! j; v+ _
- /*6 v3 [. Z N) [1 A' [7 i2 q1 h
- * 函数名:DHT11_GPIO_Config0 |6 p9 x. z& ?# d8 R: S7 G
- * 描述 :配置DHT11用到的I/O口
: h$ v+ |% h3 d( K$ h - * 输入 :无
# v7 `) t3 |9 @0 A/ y. Z% I* ? - * 输出 :无' ^( O. `/ g- l* S, n) B. v3 J0 |
- */
. C7 V- v, ? b/ Z# ?. n3 o - static void DHT11_GPIO_Config ( void )
$ X5 e4 C6 m! C: k& R* i - {
8 b1 ~9 q1 V7 P4 F& |8 m - /*定义一个GPIO_InitTypeDef类型的结构体*/
( A0 N7 ?* W3 @# F4 z$ V! `: C! i4 x - GPIO_InitTypeDef GPIO_InitStructure; 4 N, l1 Z- Q+ b1 x' x0 F
. u. z% g: S' ~9 c% j* k8 `-
0 f+ x( r0 o2 A1 r9 S# Q; f* } - /*开启DHT11_Dout_GPIO_PORT的外设时钟*/: Z% M& p- L& C+ M8 F8 M
- DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE ); $ N+ K$ h9 s& x+ x8 g# [) W
- 9 j2 j% w5 y" `$ Y2 u4 U: K
- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
8 v* T7 d ~) U. ^4 f - GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
0 l6 m& {2 L" [! B - % F% ]6 w @: k
- /*设置引脚模式为通用推挽输出*/. G: ]/ u. O$ D: r7 r
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 3 S( \7 \6 c( C l3 v
% v6 [9 B: s0 W0 ?0 k8 T, L1 u- \9 g- /*设置引脚速率为50MHz */ 8 G1 R# _2 z% ^% n$ r
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
. w1 W* `% z+ [4 {. w( f
; k+ Y5 q6 k0 [" _. d- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
% G5 O9 ~! X$ p+ \; D3 X: U; r5 \- d1 R - GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure ); & X- ^8 F8 \ s7 P" f" Z+ X
-
/ \; [0 Y- m+ X5 O5 g" M - }: {' E! h7 [7 j# i7 Q- L1 b
- % u8 Q+ d* [0 h' e! I* H8 w
- /*
' j3 X; G! U3 T9 H - * 函数名:DHT11_Mode_IPU. J% `& B- h% l* t9 F2 `
- * 描述 :使DHT11-DATA引脚变为上拉输入模式- E5 `5 p! o" d! A$ M* X7 N
- * 输入 :无. r/ z" D [2 J x2 `8 ?2 N+ m: e
- * 输出 :无
0 F; g( h( M/ B - */
; D7 N' M. w) S6 O - static void DHT11_Mode_IPU(void)
# U) @4 f3 V% M& p2 m - {1 {" b2 R! L. M, a t
- GPIO_InitTypeDef GPIO_InitStructure;
. X& {4 \1 c0 x! ?" b4 O - + U8 Q7 k& F; b* P4 [, @! X7 \
- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ 6 { T& R2 C" R: w7 v- j4 u. _" ^0 r
- GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;; R5 l# J: x5 z& U
- * ?8 q( H9 M8 {9 ~
- /*设置引脚模式为浮空输入模式*/ " k& Q& b) M1 X; r1 t
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
: k% Z, a' M, b' q4 { - % A/ ~. i1 R v, f4 D4 C
- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/( b4 n8 z5 G' d* y; j/ }5 z/ w
- GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure); : A. t! q, C+ f5 b$ A
- % {, i" S! U5 {4 K9 W& f5 B
- }
. h- B6 w% h/ ] - ) X/ |$ H T' J l
- /*
! g5 G. K5 ]1 I4 `, }( X. _ - * 函数名:DHT11_Mode_Out_PP" g! q/ i. D$ |" @+ H7 s- A
- * 描述 :使DHT11-DATA引脚变为推挽输出模式
( v# [3 J1 { t" a4 p8 M3 ^5 Z& [ - * 输入 :无
2 t. j) N/ y: [% Q) c - * 输出 :无
1 i: I* Z, L5 I/ {3 h1 h - */3 P0 Q1 p% K/ s5 I3 W2 l
- static void DHT11_Mode_Out_PP(void)0 w2 P1 f3 V# l' x0 D K, F; U. q
- {
$ J- r% J4 [2 o. F, i7 `0 Y - GPIO_InitTypeDef GPIO_InitStructure;- K2 {# G- \ z6 I
- 0 ?2 v) k5 `* ^/ ~3 o5 L# f. a
- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
0 J t/ s; J! L6 |9 `- } - GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN; " }* G4 e9 p1 o7 P
0 f8 _9 `, c& x9 N7 u$ u% ^9 Q$ @- /*设置引脚模式为通用推挽输出*/. B' N+ P( O7 M4 p s5 h
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; & V' n) @9 ]) c8 [ c; Z* X+ T
; u4 _- U6 f6 f \1 h- /*设置引脚速率为50MHz */ , l& v% f# M+ n9 i
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1 l* X* A$ R) M$ `" W
/ A1 e8 N b. ]$ K, m* e( E( m- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
, c1 v* r+ l7 f - GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure); % {3 O4 S$ C0 F3 x
-
+ Q; D& f( u2 t4 y! p$ t - }
7 j- h+ @- }" Y; G l - - o& e1 t4 }+ X# S1 s; @
- /* ) B, c* i8 B& M
- * 从DHT11读取一个字节,MSB先行1 s1 D0 P9 @, J$ j+ M' _% ~
- */8 p/ ^) `7 T6 M! }0 P2 ^
- static uint8_t DHT11_ReadByte ( void )
9 ]/ Z! t& e- A - {8 P5 T+ [' Z: ]* N3 r
- uint8_t i, temp=0;
6 V7 E1 @ m# F X" `% k" c - [, D( s/ a& C, s4 K
4 m) J5 X8 R: b4 C3 `9 Q- for(i=0;i<8;i++) $ ?4 B/ \) T7 W, d( x# S8 N
- {
: m2 A! { a- P" m# |3 g# m. z+ H - /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/
4 S, o. C/ O# M' g/ p4 r5 p - while(DHT11_Dout_IN()==Bit_RESET);
# t/ ]; h: ]( l& \3 ]! W4 l' I& m
) U" X* R, D$ K1 A2 P5 k- t- /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,% C$ `. f9 I" f8 j7 l* p
- *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 9 S3 o2 W$ n! f
- */ ^ c; T+ N( m$ |' U- }8 F
- delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可 ) v( Z7 t2 b8 q
- + r8 t$ c% X b# U0 R5 q
- if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
7 t, Z: K1 L7 w: y - {6 c+ d4 G5 @5 a
- /* 等待数据1的高电平结束 */
" h% g9 ~# L9 I7 H* y3 @/ A - while(DHT11_Dout_IN()==Bit_SET);6 y T, R; A* W7 ~
( Q+ R/ U& v7 c: ~' G- temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 , {+ @% U9 |. A9 T# p, {
- }
) j/ Y; e6 K7 Q7 K k4 q - else // x us后为低电平表示数据“0”
! T; @. b9 L: h! Q7 w - {
& b! @- r, `7 N' H - temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
/ e7 z5 W- C1 R) A' v - }4 n4 k7 |8 @& f
- }6 @7 [" s* W& {. g! c) h$ u& p
-
9 e m# t/ J0 }% N9 @ - return temp;
$ ?4 ^1 I/ o3 A' g, Z N1 J1 x9 V -
* W3 t! s4 t: q" N7 x - }
' l" U$ U' A( s- ~
/ ]1 }* V* D2 K) Q
0 t7 s7 x$ A9 Z! b2 ?0 R- /*
( b+ d9 \2 z) h! [2 V) Y - * 一次完整的数据传输为40bit,高位先出% S$ z9 K* a% {9 z# e1 N& p, X
- * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 / ^% N) K- ^( M! {, C B
- */
' O; |4 u, a" ~8 f - uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
: ]; Z& N% r! o - {
- A' [# g, u+ |+ x S) @- t - /*输出模式*/
: m6 O3 X9 [# G# b6 X6 t - DHT11_Mode_Out_PP();
5 _- y' p' E- r/ [% s - /*主机拉低*/
9 J5 }6 h- a# Q0 X0 r5 g% B9 x - DHT11_Dout_0;" `, h3 _ A g: H0 D6 U
- /*延时18ms*/3 e# `8 o3 g. z) P3 K( z
- delay_ms(18);
& [) g5 g, P- L5 w
. _5 |0 I1 `+ T4 K' [ A3 l- /*总线拉高 主机延时30us*/
/ e: i1 P& e/ P' a - DHT11_Dout_1; 0 C0 e" ]5 E: W
P+ e! S6 v& A/ g2 A- delay_us(30); //延时30us
, u3 r1 e$ }2 e+ f% a/ J( T
8 _% C! S6 l4 v* v- /*主机设为输入 判断从机响应信号*/ 8 G! v' R s- E" g. A
- DHT11_Mode_IPU();
# t! n% E+ B! [' |2 n - 2 y, a+ ]( Z l+ V" E9 ]: T
- /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
9 S/ R& z, K% z* v! o, |8 V - if(DHT11_Dout_IN()==Bit_RESET)
& |/ W. P% N0 b% ^2 n2 z& k - {+ M6 P3 U* s, t& M# k
- /*轮询直到从机发出 的80us 低电平 响应信号结束*/ 4 H) p, s" ] n) z0 \6 z
- while(DHT11_Dout_IN()==Bit_RESET);/ i- T% Z. z: V& Q8 r9 @& Q) }: }
- : U0 w v# l: |0 l. P" Y
- /*轮询直到从机发出的 80us 高电平 标置信号结束*/; z! `0 h3 N& Q; G+ T; L
- while(DHT11_Dout_IN()==Bit_SET);4 q$ Y" y9 N6 ^; Y9 L* h
- " A8 O `4 x) @- S2 C M: C& ~0 r
- /*开始接收数据*/
& O( N+ r; n8 T" W$ I% d, t - DHT11_Data->humi_int= DHT11_ReadByte();
2 T/ H! E2 X! M1 A& {
) \: k. I- A: N, f- DHT11_Data->humi_deci= DHT11_ReadByte();* |' \9 X3 B+ Y# q+ q# U0 L
- , N) B% M+ Y* M0 J9 y
- DHT11_Data->temp_int= DHT11_ReadByte();
3 z% Y7 n b; w" }8 P
. I! }: f, y- \! q6 d+ ^- DHT11_Data->temp_deci= DHT11_ReadByte();
* T5 R) r/ R+ h, i/ L+ Z( p
8 C: D) D: v9 `5 C- DHT11_Data->check_sum= DHT11_ReadByte();
+ ?! v4 r6 y8 L& G' s
8 R# w1 u: ^& A: V0 k
% F' L/ B* l3 g6 w- /*读取结束,引脚改为输出模式*/5 ~+ Z; e% t1 h* s2 e: b9 T: I
- DHT11_Mode_Out_PP();4 e) V A# M7 s3 }* p$ ~
- /*主机拉高*/
' L9 \- Y7 J# C* O6 B" H& U/ x - DHT11_Dout_1;
5 N6 y, g! O' }
1 B4 C+ a2 {, h, b+ w2 f- /*检查读取的数据是否正确*/7 i: `# S# M$ I) z
- if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
% d6 J6 t+ M1 G- k) K6 K - return SUCCESS;
2 K* d. u! Q, C* a3 I - else ; E- s$ ?/ D& p. ?, x
- return ERROR;
% Y+ g. J' G6 }; R7 C - }7 i* X* F, G2 @; r; y* V
-
1 b# i O" {2 `/ S3 r) @ - else
4 R# [7 C$ B h! G0 \7 h - return ERROR;, j- Q( T7 O+ ^4 \
- 5 q) w6 }8 A/ Z$ t4 W
- }
2 m4 x3 \' }" E; _ \ a& y
, ]- j1 ?/ ]7 u4 ]3 ]; p
. Y- E$ D/ \8 Z0 ?
复制代码 9 ]6 v7 ]% i. G5 m
3.main.c! \* M. N. ~2 @& t( V1 N
- #include "stm32f10x.h". s5 D h5 ^5 N# \+ x5 Q
- #include "delay.h"
- L: ^+ N0 W8 u( T* G4 m - #include "usart.h"
; \& g4 n- r- b" L. v3 k8 L - #include "dht11.h"
& L: x/ o6 A, ^3 W- _ w, B - # b1 ? q6 x' |* }. T
- int main()
x- g) D/ j3 x3 D! c - {( `; H8 e0 N. G" q6 c, Q6 P3 Q
- DHT11_Data_TypeDef Dht_Data;
1 u" s' ~: p# j; ? - char Temp_Str[ 10 ] = { 0 };
$ {; a% f/ K9 ~/ C7 U - char Hum_Str[ 10 ] = { 0 };
! r' G7 ^0 c7 C8 e% U. A D; N - USART_Config(); //初始化串口
( l3 ~# X/ K3 u% m. f - SysTick_Init(); //初始化系统定时器
; O% h1 j) P$ R1 m* m - printf("\r\n***Dht11 温湿度传感器实验***\r\n");
' i# O. b5 X, x. x- u5 `0 t) s2 C - DHT11_Init(); //初始化DTT11的引脚
" K9 D; i/ n' m4 c9 C7 O# ^; P - while(1)
$ k/ B2 F* M1 t, ~ \0 c - {
3 g" S" n: \$ V! A% y - //调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息
& R7 @: A" c( R% o - * h2 M' t8 N. N9 H& {
- if(DHT11_Read_TempAndHumidity(&Dht_Data) == SUCCESS)
, w2 Y; K/ N% [+ s* K5 i - {
5 \) b0 Y4 s/ \3 \4 M! ^3 Y. D - sprintf(Temp_Str,"%d.%d",Dht_Data.temp_int,Dht_Data.temp_deci);
7 T0 B$ E' F& P( U6 \7 Z - sprintf(Hum_Str,"%d,%d",Dht_Data.humi_int,Dht_Data.humi_deci);+ m3 P7 d2 }& _7 i( ]
- printf("温度数据为:%d.%d ℃\r\n",Dht_Data.temp_int,Dht_Data.temp_deci);
) t1 A; S8 V. h# o( \, h4 t - printf("湿度数据为:%d.%d %RH\r\n",Dht_Data.humi_int,Dht_Data.humi_deci);
+ x# T) d" p" W/ j6 z( G - }
8 {& S7 ?. y* o5 d- w" N% \* ` - else
& p/ b) C! B) [8 K - printf("error\r\n");
0 l) E* a" f# V) k6 i+ Z$ p- U
: \ |; g! }) z. F0 f' j3 }* v- 7 v9 M! {1 D4 d
- delay_ms(2000);. C" X" X% `: a* \9 Q" w
- }
8 U u2 b# h( z) j - }
" |- D J# b# }. ?0 G( `
复制代码 ; x. a. t/ M$ K; y3 o
% S: m$ H: M; ]$ u1 H! j. t4.串口显示
: ^: m: k$ \: \ o8 A3 g将开发板连接电脑,然后打开串口调试助手,就会看到温度以及湿度的数据
8 P. l: J9 {4 L# Z q
8 d: B$ {( w4 w5 i
2 T7 V# \* _) Y' D, T' ^4 p
. c$ Y" Q3 z* y1 \5 s
/ h# Q- _! A& M; W3 J0 S9 W
总结
' E; J" R0 M! U- j做到这一步算是已经完成温湿度采集并串口显示,有需要的话可以进行LCD显示。: u/ ~/ [! z# h" y; g
————————————————
+ v- i% M1 X3 U4 O4 Q8 a9 u6 O" |版权声明:清道 夫! ?$ ^% p# u% q6 p& P! [! v5 s
+ h4 \4 T1 ?+ [# O& @" s
. [7 |6 e! c( p
|