前言6 I) o% \/ a1 b% o% u
了解DHT11温湿度传感器相关知识,进行DHT11传感器的开发及数据获取,并通过串口调试助手查看
) L7 G4 A7 D8 }: c! a+ v+ J
3 w# @7 X; x" r$ ?; ~5 C/ e3 Y一、温湿度传感器相关知识
2 Z: P+ ]& t! E& p0 b) _1. DHT11简介 L! M8 L4 ~3 E/ u# O; ?: j
DHT11温湿度传感器是一种比较便宜的常见的温湿度传感器,它的内部由两个元件构成,一个是电阻式的感湿元件用来检测环境湿度,另一个是NTC测温元件来测量温度,在测得数据后,两个元件会将数据传送给内部一个集成的8位的处理器来对数据进行处理,并将它们转换为数字量,这些数据可以通过串口传送给主机。DHT11温湿度传感器有四个管脚,只有一条是数据线接口,所以在传输数据时仅需要1个I/O就能同时传输测得的温度以及湿度,在进行程序编写时更加简洁方便。因为DHT11集成度较好,体积比较小,所以消耗也很小,抗干扰能力更强,稳定性较好,不易受到外界干扰。 K1 q! K4 h1 c7 K& f f/ K9 e
- A \/ w9 O' a, s7 e8 n1 WPin1 VDD 供电 3-5.5V DC
; F V0 P2 y" i, XPin2 DATA 串行数据,单总线
! |- j4 i+ A' h% `+ z E: q9 ~5 A1 p IPin3 NC 空脚,悬空3 c( M8 n& p6 A6 a
Pin4 GND 接地,电源负极
/ v9 S3 `' m# J3 I: l' j' O* C2 ~) u- C7 f6 z7 M+ @% q* ~
DHT11集成度很高,封装的很简洁,只有四个管脚,所以连接也是相对比较方便。DHT11管脚Pin1接一个3-5.5V的直流电源的正极,管脚Pin2为数据端,主要用于传输数据,但是在接线时需要加一个5KΩ的上拉电阻连接到主机MCU上,用来保证数据传输的稳定性,同时还要注意这个5KΩ是在管脚Pin2与主机之间的接线小于20m时才有用,在大于20m时就需要根据实际情况来确定需要加多大的上拉电阻来保持稳定性。管脚Pin3不起什么作用,只需要将其悬空不接线即可,管脚Pin4接地。/ S: e! o: c2 M" A: [7 q a
! r& F- S" Q% c/ y' R
3 m$ F, a7 H7 Z9 B' { t/ W2.数据格式
: Y2 @8 l7 l2 b$ I6 N* E gDHT11和DS18B20不同,DHT11不需要配置,可以直接读取数据,一次完整的数据传输为40bit,先传输高字节的数据再传输低字节的数据,也就是低位后出,高位先出模式。
9 d) ]+ q% C8 T f* {9 B1 ]数据格式: 8bit湿度整数数据 + 8bit湿度小数数据5 n$ X( [% n$ {9 \! g
+8bit温度整数数据 + 8bit温度小数数据# F: I) H, _/ ~" d4 [7 X! _$ P
+8bit校验和
" P$ Q# N# \; R6 A5 k) [1 p数据传送正确时校验和数据等于. N% {2 M' G$ v1 n) W4 Q; T2 t
8bit湿度整数数据 + 8bit湿度小数数据
6 [/ d& S3 ]) R0 b+8bit温度整数数据 + 8bit温度小数数据5 {& N* a. W- z5 c
所得结果的末8位。: O, R0 r0 c* ^7 a+ e. y _8 H6 o
, s3 C5 R4 C! q
2 u7 K% o# G& B7 Q8 e9 P. l9 G3.数据传输
$ _ V( `1 R" C4 F& S数据线一开始处于高电平状态,用户MCU将总线电平拉低,表示用户要开始获取数据,然后将电平拉高并延时等待一段时间,等待DHT11回复,如果DHT11将总线拉低,表示已经收到主机信号,并响应主机信号,准备输出,然后将总线电平拉高,并延时一段时间,表示准备传输40bit的数据。然后将数据总线拉低一段时间开始传输数据,主要是进行2进制数据传输,传输0和1,并用不同的拉高电平延时时间来表示数据0和1。用户可以选择读取湿度还是温度,整数还是小数。并且数据传输是需要DHT11收到主机MCU发送的开始信号,才会开始采集数据传输数据,而且此时DHT11会转到低速模式。
# Q; s. B- v6 g+ L2 J
^; a. E# w: e8 `1 d
E# a) x+ K+ c. n& E" u
- P9 O s" G. J# K; H/ x' _
总线在空闲时因为上拉电阻会处于高电平状态,主机用户MCU会发送信号将电平拉低至少18us,太短DHT11可能会检测不到主机的起始信号。之后主机会再将电平拉高20-40us,DHT11识别到后,会将电平拉低80us,表示DHT11已经接收到主机发送的开始信号,之后再将总线切换到输入模式,然后DHT11会再将电平拉高80us表示竹北开始传输数据。之后会再将电平拉低,然后开始传输数据。
* a% y9 S: B$ u) ~8 V" H
! U' S! I& k, K2 B5 p4 P( O9 P- p当接收到主机的开始信号后,DHT11会将总线拉低80us来发送响应信号,表示已经接收到,然后会将总线拉高80us,并准备发送数据,每一位的数据都以50us的低电平间隙开始,就是每两个数据之间都有一个50us的低电平信号来表示一位数据传输完成。DHT11用电平拉高延时的时间来表示数据为位0还是1。通常用拉高26-28us来表示数据‘0’,用拉高70us来表示数据‘1’。当最后一位数据传输完成后,DHT11会将总线拉低50us,随后总线又会因为上拉电阻将总线拉高,并处于空闲状态。5 q: s |7 q. T
1 n. \ O! |" n/ eDHT11读取数据“0”时序图
( T. B* p8 P- A3 U2 u: [& U; {; V* g* u) Y% p8 g+ T
0 }% \- j8 c$ ^4 K6 q
2 ~5 u& l2 O9 R5 Z% t i
DHT11读数据“1”时序图
* U h$ k( @0 }* h" V; x/ f) h& J* P3 ] E5 m' [
1 ^- p/ [, H# ^ w n6 i5 B
, ]; b! Z8 N5 F6 J) d5 Q8 b" s3 l) K4 [5 k. x
二、程序实现' s( v1 _4 _* C/ y
1.dht11.h
' ~' Z* g% O' @/ S( jDHT11的程序实现主要是根据它的读写时序来实现的,因此在进行程序的编写时要根据它的读写时序进行模拟,实现单片机与DHT11之间的数据通信。# x, R! {, z# Q, g; |7 A- ^6 j
$ z( e6 i8 ~5 ?代码如下(示例):. q6 W* B+ [! i3 r
- #ifndef __DHT11_H6 ]5 r; |- ~' V& y
- #define __DHT11_H
" M! G9 q& j% G; B& M5 ]! ~ - - }4 F# ], `, T7 Q% m$ l
- #include "stm32f10x.h". Q3 R5 M. e' _- ]* z8 g$ z; e& \4 T- g
0 y2 V6 U* ?$ r- typedef struct
+ {' c% ~3 l3 @# Q- T' j: P - {
( j5 q- V% o r/ o1 C' g - uint8_t humi_int; //湿度的整数部分
2 Q5 j( r5 q% c8 S - uint8_t humi_deci; //湿度的小数部分$ ?( X9 I: B; i6 @
- uint8_t temp_int; //温度的整数部分
9 c2 @: r2 ^5 a7 x: b1 d+ w4 d% X - uint8_t temp_deci; //温度的小数部分
) V D( O5 n* m. @9 H- @ - uint8_t check_sum; //校验和
1 C- U* z# Q; j1 m7 n - 2 W! Z7 i, x! x* \( v4 M6 {
- } DHT11_Data_TypeDef;8 V8 K0 t" x- J
* u x; @4 |7 g, T4 A' k |- , X a5 E" H5 M$ v( C3 j* e' F4 b
- 8 ~7 w+ b, B3 X# L1 K2 {" N
- /************************** DHT11 连接引脚定义********************************/
/ v9 S* P& D' X) H/ [. o; c4 O8 ^9 U - #define DHT11_Dout_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd+ P x3 w3 f1 X+ C% o
- #define DHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOE
9 s( i6 T) b- }, Y! a - ; u) ~3 b2 ]1 R4 m
- #define DHT11_Dout_GPIO_PORT GPIOE! E0 Q% j$ H! b3 j* [, z
- #define DHT11_Dout_GPIO_PIN GPIO_Pin_6/ e1 t0 V O& l4 u: y
- 8 |) U4 k6 P6 \. R8 A C% j) |7 M
- ! i9 p& J% E4 \9 h/ y5 S
0 P) E4 p H% f, }- /************************** DHT11 函数宏定义********************************/ `: z( P# i N! C; Q8 B* ?
- #define DHT11_Dout_0 GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) 6 y9 N. A% c) {* `( p/ Q
- #define DHT11_Dout_1 GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) 6 E6 M/ P& h3 l8 B2 d
- # W g- p( v! G3 Q, \) c# p
- #define DHT11_Dout_IN() GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) * ^- b/ z3 ^+ Q0 i
1 t( W' K$ Q7 c! |
0 t( R3 v4 s5 X! I0 j% a- 5 k P. \0 x/ n
- /************************** DHT11 函数声明 ********************************/
# F8 }, D9 {& V p0 O5 d- F - void DHT11_Init ( void );: P$ u. | m5 |4 G! `* l
- uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data );
% V: a, c; `( x
! V0 i4 B+ I8 w7 c/ ]- #endif
! y# i5 z" S) ~+ m* h) N; j
复制代码 " T( X+ {, `+ T# d4 t9 n
DHT11用到的数据总线是PE6,接线时,DHT11数据线接到PE6,以及我们需要用到的函数的声明:7 c' H* r0 q$ l
Void DHT11_Init(void)为DHT11的初始化函数;0 B" U6 I, R' |# B+ V
uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data )为DHT11的数据读取函数,这个函数会将读取到的数据赋值给DHT11_Data结构体里的变量,然后还会有一个返回值判断是否读取成功;
( v9 o) P. c: R* {# `* Q2 o
. L/ \$ d( J/ c/ }2.dht11.c1 G( r% x: s" A# e4 b2 y
代码如下(示例):; q3 P2 }* ^( C! W! j- Y
- #include "dht11.h"
0 z+ [: j* T# N* h/ _ - #include "delay.h"5 `) p& a% ~9 g+ q
- ) \/ c4 G7 H) N8 a g9 V- N
- static void DHT11_GPIO_Config ( void );
- N2 d! n+ U u i - static void DHT11_Mode_IPU ( void );
. G# z" T" y* t8 P - static void DHT11_Mode_Out_PP ( void );
$ c& ~/ K7 x8 Y& T2 X P' B: h% P - static uint8_t DHT11_ReadByte ( void );
# N- U6 T8 i _5 j
. @+ `$ ~7 u9 C* b- & x% u% q: Q) A ~( `* y
- /*** M$ b4 q/ @2 s* m3 J
- * @brief DHT11 初始化函数5 @: I4 ^( u1 A0 X- w O2 J
- * @param 无
+ H3 x3 h5 f, y - * @retval 无1 P6 r, t/ V0 ]
- */) {- w7 |' m8 t
- void DHT11_Init ( void )
- y) G4 m6 O6 z. m/ [% v. O - {
" T7 c; n* v' N; ^6 F7 z7 N - DHT11_GPIO_Config ();3 B8 m# v n. N9 J- e. B
- + J- z5 V4 Q/ \5 c& r6 A
- DHT11_Dout_1; // 拉高GPIOB10
' v4 Y$ C' [6 t, D& C - }. e. I# z5 C. d3 o2 M' q7 c
' R& l) g+ M' ~% N- /*1 B$ P Z0 U" m4 @$ Q7 A
- * 函数名:DHT11_GPIO_Config4 b$ J5 N ?8 i9 S4 u% r; Q
- * 描述 :配置DHT11用到的I/O口
2 O2 g1 A* E! j0 x - * 输入 :无& p! }5 D4 ?+ f) u0 i
- * 输出 :无, M3 m; f+ ~$ ~5 T9 q) B" t* x* w+ G+ c
- */
! m) T2 C" G& Z7 r - static void DHT11_GPIO_Config ( void )
! t) x7 ~& H: {! l2 t, ~& l - {
; O0 s6 I y$ ]$ k6 @! b$ ]; O9 ^ - /*定义一个GPIO_InitTypeDef类型的结构体*/
/ v$ q( P; m) C2 L& r$ v) t5 A - GPIO_InitTypeDef GPIO_InitStructure; + F% ]) [8 s2 C# f) ~% W
- + N3 j, C1 w N$ G, B' A! ?
-
- z+ @9 q! j9 {. C4 B - /*开启DHT11_Dout_GPIO_PORT的外设时钟*/
4 f, a/ b! w2 U( v, g! Z - DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );
' _8 w& t0 W4 P2 g+ b( r2 w - . |: _* m5 ?* U7 w4 N. ?9 ~* A' y
- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ 8 e: ?( n$ B7 t) X3 O4 u
- GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
, U3 R5 {! P" T& R, t - 0 W& W$ j6 j+ f; D
- /*设置引脚模式为通用推挽输出*/
, F7 [1 l$ i& Y2 F% I - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 4 q- I1 h' B( g2 q- B
- % k. a- m: E8 W; L! I# p
- /*设置引脚速率为50MHz */ 3 C- D5 O% W& { C3 |
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
( K" z- X3 A+ |4 [# X0 d
, D3 W ]' ?3 b' O* f$ q- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/" v9 w- c4 ?( ?3 a; [
- GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );
0 T" ?8 n/ ^. k" L- k3 Q -
; y( A7 D& Z; g3 D2 X) g - }
2 F& {0 V" U! | - 9 K3 Q# Z; g8 O2 V& I
- /*
; I( K5 v9 L% g+ M, s - * 函数名:DHT11_Mode_IPU
2 S/ y! {' ?, N1 @$ ^ - * 描述 :使DHT11-DATA引脚变为上拉输入模式4 i8 c& x! w; ?
- * 输入 :无6 _" t1 j: A) o8 H
- * 输出 :无
" w3 a& S& t) |0 B- Y - */
# Z) W% ~' j# V; k' W - static void DHT11_Mode_IPU(void)
# C, y$ x- l# d/ ?! L3 n: C, X - {! a' Y* u* `$ l! r
- GPIO_InitTypeDef GPIO_InitStructure;9 F- B. u3 l% ?4 j6 |. w# _
) j: E: B; ~5 [7 ^! }0 y- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
1 @7 C8 Q* q' N# J - GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
1 W/ j- j5 E, T# ^/ m - ' L- Z# T3 r/ B, k/ b0 L4 H) z( ^
- /*设置引脚模式为浮空输入模式*/
: U9 [0 Z! a- f - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 7 I, H8 {9 B9 ^" _
6 x: W0 N5 A& v. p3 o) E- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
$ H1 `# E2 X2 Y, ^% r2 ^ - GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
( ~$ t3 s; J: U& u$ B -
! x) H9 \$ R+ G* C: Z - }3 u- W$ ~: @" u. J3 \( _
- * }; \: l# ~. E2 J/ L7 i' \
- /*
! H' ` G# K4 s6 S8 \% K) H - * 函数名:DHT11_Mode_Out_PP( J% @ l% a& W
- * 描述 :使DHT11-DATA引脚变为推挽输出模式& V0 X% q) g' T9 ?8 ^7 F+ [) f
- * 输入 :无
! F- C) I/ n: z) v - * 输出 :无+ b, u6 `6 t V
- *// M) |8 x1 z. X, G; R! x
- static void DHT11_Mode_Out_PP(void); C& t& J5 }0 o& E5 @2 E
- {3 v+ O9 j- e v7 r
- GPIO_InitTypeDef GPIO_InitStructure;+ o: A; n1 S/ q
. ?( ^2 Q+ @# q- /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ : u9 A3 G/ D. H @1 q' w
- GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
2 n3 N8 h* l$ E; E8 Q
+ o$ m' T: p {) s- /*设置引脚模式为通用推挽输出*/
- z5 a+ R3 ]" P - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
) v' i( S# \9 R# }" V
; x: ]3 t: n, h8 v. x" e( H- /*设置引脚速率为50MHz */ & D, Q% _1 J% A$ a/ A
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;7 E+ u) w+ j, k2 d" B6 \& [4 }2 J$ V
* K$ @ \! I% Q1 F6 T; Y9 U# h- /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/2 G: R- n, {! |$ Y, G$ m+ V4 L
- GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
' e! P' e% S0 t6 X3 q; ? -
# @5 E3 X9 b: s) e - }
6 h7 X+ q: W. y- b
- L& t* \* w* ~2 Y; m0 Q" s% j- /*
; V; E8 L6 b5 n" s' W" J3 `1 g - * 从DHT11读取一个字节,MSB先行
: i* H( l! N* g( l2 ]2 J0 F1 L# k - */
/ y7 Q6 ^7 \2 Z; F% \" P, { - static uint8_t DHT11_ReadByte ( void ) r+ n8 v2 l% B0 O3 x; O
- {7 t) b" _7 ^" R
- uint8_t i, temp=0;
2 J$ S5 | M Z' w -
8 o$ Q. y+ b0 |9 c
$ v3 x% H0 L! Z9 A/ \( g9 Y- for(i=0;i<8;i++) 1 n# C9 k# [0 A) e
- {
2 \) L- s- w- R2 s0 h$ S - /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ 6 i- n* t( `! ^
- while(DHT11_Dout_IN()==Bit_RESET);* P" w" f; X) U7 p8 K
- $ [4 j2 ?+ H3 j$ v) x. k) u) Y+ ^
- /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,% W2 z6 X& s$ `! w
- *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
" L# W8 H! t8 Q- B" B - */5 y0 d! N5 C& F, i% l5 ~. ~
- delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可
! _8 F" U% i7 n( a+ m
: M6 a% j/ t1 C8 s" t7 ` Z- if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */ x7 M/ N& j1 }) M" J! D9 _# J
- {
0 T+ C" m; K3 I9 s3 w - /* 等待数据1的高电平结束 */
" r& `2 Z+ K- Y( F4 z - while(DHT11_Dout_IN()==Bit_SET);
9 I' q* ~1 n S O' p
6 o$ b) {$ o. `% I- temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行
p4 g4 s- ~2 Z% x6 O* S - }( S' |9 }' n" a' ?% g) \( }
- else // x us后为低电平表示数据“0”
7 W% Z$ B( c0 _5 @/ x - { 2 @) s( v7 v% z2 X3 m- n" _- G" f4 e
- temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
+ @7 H! M& {. g7 {4 S5 U6 @ - }
4 l" p K/ a# L/ V - }
/ A6 `3 W$ B% d5 b( s) U -
" @1 g! O( ^! l" E; l% u - return temp;2 G0 b# s/ x' W9 n
- + v8 M, P/ O& Z/ _/ y j+ l0 B
- }
$ A% \1 \2 L4 H0 O2 P Z
$ D6 R$ o- i6 ~. R# y* k0 y. i6 l- & C; u6 n+ P6 A. }" T3 I. f
- /*
" Y2 \( b% t$ q: V - * 一次完整的数据传输为40bit,高位先出
9 T6 L# V* w$ x2 I3 r- R* F - * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
# B4 L5 ~/ t# T2 l# \ C - */
2 ?9 j, P9 f; i2 [1 ] - uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)/ E5 z9 H" ~# Q0 F' y
- {
3 j) ? X- a$ D# b - /*输出模式*/" f- E5 e( T3 M; x( n. Z
- DHT11_Mode_Out_PP();: r8 W& N2 q3 x* e: K. ^' | B
- /*主机拉低*/
9 F( R& Y! K! w0 Y( L - DHT11_Dout_0;
; L9 |" C0 o3 s, \+ W - /*延时18ms*/
$ M0 `- a% O- W( V5 m - delay_ms(18);" B0 X1 Z# R% H5 J( Q/ e
- % q. [9 k7 S& `& E* `1 q" ^( f+ @0 L
- /*总线拉高 主机延时30us*/ J1 _6 J( t, c, y' K9 G5 l2 S
- DHT11_Dout_1; # P$ {% l: k0 X# a+ {) D. @1 [
- ' R( `: P" M @! q
- delay_us(30); //延时30us
% |2 a' Z6 m0 _: M6 _! Q
) ?2 \' C7 G# b8 v' d( M' p- /*主机设为输入 判断从机响应信号*/
) D5 h, c8 a% z j- h - DHT11_Mode_IPU();
0 I- @/ c8 o, d - & v0 g7 q2 ?" p, s: u4 x4 B; q6 J
- /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ " n6 c( V- ~/ b- V
- if(DHT11_Dout_IN()==Bit_RESET) & W% L# @8 @+ ~! U
- {
) F, y( ?# q5 p. y - /*轮询直到从机发出 的80us 低电平 响应信号结束*/
4 u6 p7 r& u1 N! ?& X8 a) t - while(DHT11_Dout_IN()==Bit_RESET);
! y) q% \3 i# n M' C: k
5 N' N" ?5 @3 L" v- /*轮询直到从机发出的 80us 高电平 标置信号结束*/4 y- c* g( R8 ]+ @! U1 x, ?
- while(DHT11_Dout_IN()==Bit_SET);
/ j5 R5 [1 g4 R/ s% g. U3 y3 T) b# m
j$ Z; ^' _" ]( p, E+ V- /*开始接收数据*/ / S; X9 Q: a2 P4 p4 F
- DHT11_Data->humi_int= DHT11_ReadByte();
- i& C/ O; Q* x* R# N - 5 A0 M! |4 _, X$ r
- DHT11_Data->humi_deci= DHT11_ReadByte();0 o. D* C, X% Q: n
/ Q3 H( n/ R& A! n- DHT11_Data->temp_int= DHT11_ReadByte();
Y8 b2 o2 \/ c; D r8 t
}- h/ ~8 d. P' U' }; r) d& P- DHT11_Data->temp_deci= DHT11_ReadByte();
: B8 R' ]; n# A7 f6 n9 x; P& O
$ {5 J7 }: |. H4 X1 I- DHT11_Data->check_sum= DHT11_ReadByte();1 K: Q3 y5 r' |: h
- 6 h/ ^! X( n, q; @! x
- & y; `$ K: p- j9 T% n# V0 P
- /*读取结束,引脚改为输出模式*/
5 j r3 J T" C: B - DHT11_Mode_Out_PP();) r& ^. Q- }& x5 x
- /*主机拉高*/( b6 s$ T2 C2 S, {% a2 R
- DHT11_Dout_1;5 @; U6 b8 k! `% T
0 U7 U- ]1 r& _/ i- /*检查读取的数据是否正确*/
3 T+ B- M6 e: S9 S) ~* ~ - if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
0 j3 b' C( z3 v: F. F# \! @, k- n - return SUCCESS;( I3 j4 E4 x( I: P c; F7 P
- else
* h' N8 L' m. h8 W - return ERROR;2 l2 C8 q& z# ^- J& g/ v8 w
- }/ G& t9 k' ?( M: o2 ^* M
- 9 ?% D! f0 P" y+ q
- else
+ m8 S) g/ G1 R% k, I2 C" k% `& U - return ERROR;
. m$ C: b% ?" c0 W7 f) t0 X - ' f% ]. V3 W q w& [
- }
* C& L# K7 @8 C: l: v - ; Z) M0 q+ U/ l
- ' e9 h9 F4 W$ Z( l5 q, Q# P) q
复制代码
$ l" U8 a) e7 s3.main.c
# s9 Y) l |& @& O5 o- @- #include "stm32f10x.h"' z0 l' n4 h2 F9 ]( }' y. e" t+ u0 E! @
- #include "delay.h"
; s. \; z1 Y1 a - #include "usart.h"+ e* _) L% r2 z3 _3 @+ F
- #include "dht11.h"
" u. U0 ?6 f( [( o3 R6 u - + U0 P4 A6 o1 ]1 Q- P
- int main()
; C+ h' D4 X8 ^: W6 ` - {
& O) v' l* P8 G0 Q# d/ G - DHT11_Data_TypeDef Dht_Data; v/ Y* N, k! U0 f0 B, v/ o- l
- char Temp_Str[ 10 ] = { 0 };' o' t' D" z& C5 k/ G- u
- char Hum_Str[ 10 ] = { 0 };& R' L; Y" I7 D7 W, H' \3 X# x
- USART_Config(); //初始化串口
. r! p, |+ h* f" Z/ w, w - SysTick_Init(); //初始化系统定时器
% d T# E( }' X5 Z - printf("\r\n***Dht11 温湿度传感器实验***\r\n");! g" ]0 Y- g! R& ~" k) i$ _& ]' W
- DHT11_Init(); //初始化DTT11的引脚
5 r8 A7 I' H' c: o1 m0 | - while(1)* A2 e# W- W, |
- {3 ?& ]; a4 n* C! I9 e9 N% X
- //调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息
* H, m$ |. e2 b$ x2 P4 x
: o! x' r* ~7 d) w- if(DHT11_Read_TempAndHumidity(&Dht_Data) == SUCCESS)7 u4 }% u: B1 U; t
- {; Z; s: [: { N6 H: ?0 @& D* F' f3 g
- sprintf(Temp_Str,"%d.%d",Dht_Data.temp_int,Dht_Data.temp_deci);
4 @: [- o- s, d- ]- o% M1 K% | - sprintf(Hum_Str,"%d,%d",Dht_Data.humi_int,Dht_Data.humi_deci);3 u: j1 F( O1 Q6 V* l8 O
- printf("温度数据为:%d.%d ℃\r\n",Dht_Data.temp_int,Dht_Data.temp_deci);
: O7 c1 L5 j' F6 O5 _ - printf("湿度数据为:%d.%d %RH\r\n",Dht_Data.humi_int,Dht_Data.humi_deci);3 _; N/ V* y3 f& ^
- }
3 a6 w3 y& P/ s" i - else
3 w& J# e z, W# P - printf("error\r\n");& H$ b6 l! }* ]3 {
5 Y5 H$ h& @$ f8 F
- E* a1 ~, U; y7 ?- delay_ms(2000);
" s" Q2 r3 p( b9 w6 I- { - }
9 _/ e! p$ E) a4 @ m: }( K# } - }+ J: H$ ~3 N e; z7 W R" _. v
复制代码
/ s. R! f1 V; g/ |; j% L3 ]4 m4 T1 |4 J
4.串口显示* i0 K" N0 T) @1 m$ ]. R) {
将开发板连接电脑,然后打开串口调试助手,就会看到温度以及湿度的数据
! {. r1 ?1 X. D3 Z9 w, M8 F" x3 w9 t0 c6 ]$ a, b1 R% c# }
8 F5 K2 ?, p' K
5 N- H) n5 X* ]2 E' d' P: q3 y) ]
" ?! f5 T2 [6 I3 ?0 \/ B总结
" q2 E7 x6 P$ B做到这一步算是已经完成温湿度采集并串口显示,有需要的话可以进行LCD显示。7 E9 S* O+ J1 e+ S1 w7 H
————————————————& b/ N, W, d/ D& }6 Z( ~
版权声明:清道 夫
4 Y$ U6 [" B# B! O. |3 |; t
* u1 K* ^ C1 @4 |! x# z8 Y* c* j5 `9 o* d$ F! J
|