你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103VET6实现采集温湿度数据

[复制链接]
STMCU小助手 发布时间:2023-2-5 18:50
前言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
1d4a7e41310f44198a2a3914b9f59db3.png
. 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
ea92ef3f20334c68aa75e8b83aefa06f.png
! ^$ 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
d7d734cf63a942ecbe48dc4f2ae1fc4b.png
! 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
  1. #ifndef __DHT11_H/ b% q$ V9 }1 }$ b4 Y4 m
  2. #define __DHT11_H# D! Z! I7 ~# i

  3. 8 W" y' ]! P, q* i! Z( o
  4. #include "stm32f10x.h"; }  b: O# b! h; s' G1 u* m: D/ f' I

  5. , n1 M0 o7 q, _' L9 L" }; W! \
  6. typedef struct
    4 I0 r6 ~( x' R, m- q( z+ Z# V
  7. {, R: S/ g$ g0 D
  8.         uint8_t  humi_int;                //湿度的整数部分5 @6 P5 n* N6 b, l6 S9 e: q6 I) R9 P
  9.         uint8_t  humi_deci;                 //湿度的小数部分9 g# g: x/ {2 w. C6 q% l. C4 H. y
  10.         uint8_t  temp_int;                 //温度的整数部分2 ?4 Y! Q# A0 g8 o* o; r. G
  11.         uint8_t  temp_deci;                 //温度的小数部分
    ' l1 l& o& _( x$ ^1 |! P
  12.         uint8_t  check_sum;                 //校验和5 Y' [( j6 v& l) R6 ~) }# ?* c' q
  13.                                  
    2 Z6 `3 c6 |# `$ O) ^
  14. } DHT11_Data_TypeDef;
    * i! `  Y! {- [3 }3 x

  15. 6 b" a( Z! h5 {3 o
  16. " E0 y- m4 r8 w
  17. ! A2 f) X8 |1 ^1 B4 w
  18. /************************** DHT11 连接引脚定义********************************/' ~6 t" z7 R9 R/ }, _/ l
  19. #define      DHT11_Dout_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd9 `4 I( {* j' v' v7 @' a/ Z, i
  20. #define      DHT11_Dout_GPIO_CLK                       RCC_APB2Periph_GPIOE
    $ y3 X) a/ \9 @
  21. ( s+ M8 T0 _5 D% U( f% `/ i. ]  z
  22. #define      DHT11_Dout_GPIO_PORT                      GPIOE
    ) |* w, |& Z2 ~3 e1 W, v
  23. #define      DHT11_Dout_GPIO_PIN                       GPIO_Pin_6+ {0 H0 [7 e$ Q2 s$ G

  24. , d, x/ o% z; S& x2 g

  25. . E. ?9 R) @$ R4 V: Y
  26. 8 [2 g! v& m) N5 `( X5 |
  27. /************************** DHT11 函数宏定义********************************/" `/ ?" Z3 x4 s5 q. f- R0 u
  28. #define      DHT11_Dout_0                                    GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
    3 v* W+ C$ P6 X
  29. #define      DHT11_Dout_1                                    GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) ( [# [2 V2 \7 G% M* n( U
  30. ) [# F9 m6 n* q6 g
  31. #define      DHT11_Dout_IN()                                  GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) " _  `2 I( B! Y( g, q" ?+ b% q

  32. ; a/ G, f) z/ R8 E5 I$ B& g5 R" q) M
  33. , ]9 p* p* J) Q- ?" c. N. C

  34. + L6 g& O& `0 v) l
  35. /************************** DHT11 函数声明 ********************************/  J! Z3 s: W$ j8 x7 k4 z
  36. void                     DHT11_Init                      ( void );
    3 S+ Y8 ?( H% n/ d6 L- P( k% Q
  37. uint8_t                  DHT11_Read_TempAndHumidity      ( DHT11_Data_TypeDef * DHT11_Data );
    ' G5 e9 g* U4 H

  38. & `) D* i$ F2 V1 Z
  39. #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
  1. #include "dht11.h"
    4 O; C: T  l( Q! E
  2. #include "delay.h"1 `! z) M1 W- d# ~4 r" E% ?

  3. % [8 t# \- M1 W; y
  4. static void                           DHT11_GPIO_Config                       ( void );
    + t" `: R" R1 o3 S5 v' S
  5. static void                           DHT11_Mode_IPU                          ( void );" W  L# h4 {3 x4 j5 ^9 f4 A: f
  6. static void                           DHT11_Mode_Out_PP                       ( void );4 d) W# ~  |5 ?. a) \* [
  7. static uint8_t                        DHT11_ReadByte                          ( void );
    ( v3 V7 u* J4 O! h" [' X+ |

  8. + v  y( x  Q7 X5 m' @8 j& j$ `& V

  9. 7 `% f8 U  h$ g1 T- z7 }- E
  10. /**
    1 ]: N& u9 c4 R) _
  11.   * @brief  DHT11 初始化函数3 Q) }- H( d+ m* Z2 ]; t6 U
  12.   * @param  无+ O5 H* d; U2 ^, }' b# H7 o, z7 M
  13.   * @retval 无
    8 h' I; u% h7 e0 q& Z
  14.   */
    1 q* [9 R6 x. f7 V" J/ c
  15. void DHT11_Init ( void )
    ( n2 |" c: T/ s  Y/ x3 m# `# C; F
  16. {
    4 ^7 {5 a1 c2 F, X5 t! D5 `
  17.         DHT11_GPIO_Config ();3 X& f' {; D7 U8 e1 I  [
  18.        
    # Q! d0 P% X1 V" g' k1 V
  19.         DHT11_Dout_1;               // 拉高GPIOB10
    - M2 Q& i! I; `& s, [
  20. }
    , g; e, L0 W& F, L1 l

  21. 4 E: O$ n; d9 V3 e! M6 Y: y0 T
  22. /*! F* e# Y' J9 Z+ m' x
  23. * 函数名:DHT11_GPIO_Config
    , C' F" [; R2 I2 z/ x( `
  24. * 描述  :配置DHT11用到的I/O口
    ' K2 L9 E5 ~7 O3 k5 S9 c7 @2 E
  25. * 输入  :无" J" u% T; @5 [0 _( M
  26. * 输出  :无
    6 p0 ?7 H- r4 i. n
  27. */
    0 P* K' w' ^* N+ y
  28. static void DHT11_GPIO_Config ( void )
    3 \  @( o  z/ V
  29. {               
    $ f& l2 i+ ^' p( `( }
  30.         /*定义一个GPIO_InitTypeDef类型的结构体*/4 ~2 r5 m- E, I6 w3 a
  31.         GPIO_InitTypeDef GPIO_InitStructure;
    1 P6 F( W, _0 J3 [

  32. / M- g  w3 W4 `. U$ X3 ]
  33.        
    0 I, k2 x$ f. Y$ b9 W
  34.         /*开启DHT11_Dout_GPIO_PORT的外设时钟*/
    0 u3 g, y* C1 r, ^* O
  35.   DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );       
    4 o- [- E5 \+ N8 v9 Q

  36. 4 T8 ^+ x) h1 S5 z; t. m- w
  37.         /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/                                                                                                                           5 z+ r- G( g* R- M
  38.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;       
    ; a; M7 M! v' a" h0 e# e' J

  39. 9 ^4 M/ P, ^! b* E# F( V' N7 |
  40.         /*设置引脚模式为通用推挽输出*/2 G/ R6 w5 \2 H! C1 z+ R
  41.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    ; `; [  `  `" \) P# t& d

  42. 3 T5 h, l( H: f" h% n, W8 l
  43.         /*设置引脚速率为50MHz */   
    & ^/ c  a) \8 C4 [2 _- j3 P
  44.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   j6 |# c3 J: L, k* D5 q6 A
  45. " V4 v0 p' u  t/ y
  46.         /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
    9 v- V+ Z$ y0 t
  47.           GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );                  & x. x" a" A. p0 L
  48.        
    * h5 _. N1 N! A$ g, d$ R
  49. }
    % B: n+ r& s' b# L( U8 o, D

  50. / k  [8 {) N5 M, O# q
  51. /*9 g$ n. J# ]2 U3 ^5 |6 X
  52. * 函数名:DHT11_Mode_IPU  e% U; u3 \' ~1 e! a
  53. * 描述  :使DHT11-DATA引脚变为上拉输入模式" J$ f, V! S: @
  54. * 输入  :无
    9 B) `3 Y" [8 r- q+ X
  55. * 输出  :无% \, ^# \8 b0 c
  56. */
    + v* ]$ ^4 A$ I5 y' L
  57. static void DHT11_Mode_IPU(void)
    . ]: n: A5 c& ^$ ^
  58. {* A1 h) e( _1 C$ X
  59.           GPIO_InitTypeDef GPIO_InitStructure;2 e8 ^7 G" j! f0 n1 n3 _

  60. - U- v+ H& o3 d0 `- ?0 ^
  61.                   /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/       
    2 q9 U8 Y) F5 e3 Z9 K
  62.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
    " @+ e) o% f1 L* {
  63. 2 G- \5 B2 y+ `4 U2 ~5 F  n9 X' z
  64.            /*设置引脚模式为浮空输入模式*/ 9 S& M+ I" ?) T- [; M1 \
  65.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; & E( Q% b( Y' h& A9 s( l+ y% l
  66. 4 O2 ~- V. m7 `! o. P* C
  67.           /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
    : C( e1 T' e% _! H2 ~2 B
  68.           GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);         
    : O. ^# f, c4 d, e. [7 X
  69.         7 h2 ]; Z; }) p
  70. }2 a! R- B9 s, l( c, q0 \
  71. 2 s  P# l4 f( c( k
  72. /*
    - C+ z# M& _3 U; j4 q- B1 }2 j% u$ u
  73. * 函数名:DHT11_Mode_Out_PP* W/ _7 a8 N& z$ X8 W7 f
  74. * 描述  :使DHT11-DATA引脚变为推挽输出模式
    1 r& s) g( p, Q- c/ ^
  75. * 输入  :无1 M8 x8 z9 u1 H6 T# e5 u/ l
  76. * 输出  :无0 o8 o4 ?3 c* Q0 d3 U6 U
  77. */; }: W& N( n  s9 K+ {: n# Z' G
  78. static void DHT11_Mode_Out_PP(void)
    * ~7 h, O1 N, p8 {- S3 X
  79. {. g+ I( S1 I% A5 _6 U# @9 `0 W
  80.         GPIO_InitTypeDef GPIO_InitStructure;
    ) Y" E  ~- `. r( L3 ?% O- K+ B
  81. + v, d4 b! d6 u+ @' D
  82.                  /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/                                                                                                                          
    1 O$ I  {( t* k$ X) ~2 B
  83.           GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;        0 I* s2 r/ v8 r' Q7 O
  84. 5 i& b, y: l, o9 I1 ^
  85.         /*设置引脚模式为通用推挽输出*/
    8 l; f: q/ ?/ A2 u8 W' T) x6 W
  86.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    " t0 g. @9 c( R8 u- b9 L! J1 o2 Z
  87. 8 E  K6 Y& t& `, D$ e
  88.         /*设置引脚速率为50MHz */   6 Q" K6 X4 P" ^% X# u4 `
  89.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    4 H( o  |/ C  [7 Q

  90. 2 X8 c/ B; m0 T" j
  91.         /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/) j0 V+ N! I9 P1 y$ c/ `2 y, R2 ]
  92.           GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);                  
    4 m/ E- Z+ ]; F" P9 o& j
  93.        
    5 k0 r8 `* j8 ~- d+ u/ K' L
  94. }3 G" E9 |) F1 o4 m5 t# \& S

  95. + f: |: F) B9 J; s
  96. /* 3 W# M- h# V$ k, O
  97. * 从DHT11读取一个字节,MSB先行* K; x( Z1 K! r
  98. */
    - K; _0 t& E( o5 x
  99. static uint8_t DHT11_ReadByte ( void )
    8 @- ~+ Y* r5 w3 W
  100. {2 g( F5 R; _3 v! h/ j  s
  101.         uint8_t i, temp=0;
    2 G; a6 Q9 _1 l$ a6 u" C+ `! R; m# S
  102.         1 Z" P+ X% q0 V! D8 z6 r9 o8 \5 K

  103. & l4 x6 z, C. s2 S' J% j2 f/ B
  104.         for(i=0;i<8;i++)   
    & P* h) l- n) \2 }: _
  105.         {         : f& i5 K2 W# M3 s5 E0 c7 q
  106.                 /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  : i' r; D! R+ t! }6 s0 Q# K& c
  107.                 while(DHT11_Dout_IN()==Bit_RESET);
    8 ~8 x% [) x5 b2 N1 Q

  108. ' U2 W! U4 u# D. |9 a" `1 {$ t
  109.                 /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,/ R. o: s% }* F# K& N) l1 }+ n( s
  110.                  *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
    8 d$ V  `* R1 z2 S3 w
  111.                  */3 \2 u3 U7 R( g' i4 [
  112.                 delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可                     
    : k, Y: A- c6 d( g. `1 i: S# J) T! p9 f

  113. 1 u* i2 _1 I9 V. x
  114.                 if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */4 I/ M( C0 w0 ?% @% ^9 I
  115.                 {
    / j/ d; M% d( [
  116.                         /* 等待数据1的高电平结束 */, A& ~, {: f+ x' k
  117.                         while(DHT11_Dout_IN()==Bit_SET);
    5 x0 }2 G/ \! {+ c
  118. # l8 o( V2 e4 P$ [0 a
  119.                         temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行
    & ^0 t6 ?! \3 ]- f& u- G
  120.                 }$ I, ~1 u$ z" V0 X2 i  h
  121.                 else         // x us后为低电平表示数据“0”
    . N+ n/ K" a/ A+ x
  122.                 {                          
      j% ^, Z* L9 ~3 K6 ~% ]
  123.                         temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行2 F9 r  A: q" M- ~: v
  124.                 }% V: p8 E# |8 x; I6 ^! c: G0 p/ D1 S
  125.         }
    : f8 C* x' c) x- q
  126.        
    * C' c# ~2 p, c1 J# n4 I  x4 H
  127.         return temp;
    / B4 ^1 ^! N8 Y2 A' B
  128.         6 r! q3 _; P+ d
  129. }
    ( O( U1 s$ c( K& D

  130. $ Q/ J, s; S5 C0 ~3 {4 _
  131. 0 h: ?- ^" w" I  P  T
  132. /*  E2 @! Z! o3 [
  133. * 一次完整的数据传输为40bit,高位先出/ }( Z2 G- ~) m" E$ F/ U1 i8 D
  134. * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
    ! M- x) S2 r( R7 t/ ]
  135. */
    $ r) e1 K, o. V3 a2 v
  136. uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)$ M* ]+ t% m5 A- v! F
  137. {  - t4 u4 ?9 Z( Z8 o+ g
  138.         /*输出模式*/
    # [, x% Y! O9 e) v# m+ Z
  139.         DHT11_Mode_Out_PP();
    , Q% Y- E3 a# P: L0 g; D7 C7 u# _2 N
  140.         /*主机拉低*/0 R! Z7 J' ~/ l) H. \
  141.         DHT11_Dout_0;" N2 O+ _6 D* d4 C/ j
  142.         /*延时18ms*/
    $ B' M& c" n+ h* C; m
  143.         delay_ms(18);
      a! c. G2 O  M# `& _8 D# _/ K& _* o

  144. ' K" K) z/ T  R! ?" M5 z$ n
  145.         /*总线拉高 主机延时30us*/
    3 T( Z0 ]( K1 J/ j) J7 `1 |
  146.         DHT11_Dout_1; # f& j; T0 R. w: A
  147. ) u& W! A' O! L* H* d
  148.         delay_us(30);   //延时30us
    - a0 W2 |' C+ I

  149. ! k$ b+ ]" ^  Q- L
  150.         /*主机设为输入 判断从机响应信号*/
    9 W" a& M1 }0 W7 C& j2 b$ U) ]' `( t
  151.         DHT11_Mode_IPU();( U5 b! Y/ Q0 o; c5 p8 N. Z

  152. : B# ]7 K6 _* r  t, K
  153.         /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   " X7 m& D6 T' b7 r: T- v/ i) A
  154.         if(DHT11_Dout_IN()==Bit_RESET)     3 {4 Y& N1 y! v, W8 F
  155.         {
    # o0 x& M: ~1 f# y1 l
  156.                 /*轮询直到从机发出 的80us 低电平 响应信号结束*/  1 Q0 U, g6 ^$ i
  157.                 while(DHT11_Dout_IN()==Bit_RESET);
    1 ]6 ~0 i% q" u% X% s! T! u
  158. + b) S) @0 A, h- ^) q$ @2 d
  159.                 /*轮询直到从机发出的 80us 高电平 标置信号结束*/
    & D, a+ L$ F. i
  160.                 while(DHT11_Dout_IN()==Bit_SET);
    / H7 i& M) v5 y$ A

  161. # f0 g: D2 N. e) U$ |
  162.                 /*开始接收数据*/   7 d4 j) {& _0 E
  163.                 DHT11_Data->humi_int= DHT11_ReadByte();
    " J5 U/ Z7 L/ v9 }- f" ?
  164. 2 Y+ T  g6 j6 f0 D
  165.                 DHT11_Data->humi_deci= DHT11_ReadByte();+ c9 g! w0 }6 Q) p
  166. 7 E2 h. @' ?4 k6 [! G4 h. z. b
  167.                 DHT11_Data->temp_int= DHT11_ReadByte();
    * Z# _# @3 p. [8 G7 G
  168. ( C1 |: w1 o2 N
  169.                 DHT11_Data->temp_deci= DHT11_ReadByte();$ \( e( z3 Q8 e9 F3 c$ j- U/ E
  170. & I( y- Y. X' c: \4 N# u
  171.                 DHT11_Data->check_sum= DHT11_ReadByte();: M% ?. K& L$ @( d; w) t2 w

  172. 8 t, w6 p! }2 |+ ?# L4 _
  173. ( \: Q$ ^8 e$ T( [5 K4 w( s
  174.                 /*读取结束,引脚改为输出模式*/
    - z5 ], X5 H1 m! o
  175.                 DHT11_Mode_Out_PP();
    , x6 F  X% y- a
  176.                 /*主机拉高*/* O- o& y  t- O
  177.                 DHT11_Dout_1;
    " Y' b& j* X/ B/ w# I9 N2 [+ N
  178. 1 `# ^$ b  e' F0 D8 N
  179.                 /*检查读取的数据是否正确*/! A/ t) V% E: C$ s0 q2 s
  180.                 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
  181.                         return SUCCESS;$ y& D1 `, @- O& u9 J) d  a) I
  182.                 else / H+ ^9 s  D( f+ K+ Z
  183.                         return ERROR;
    % y& W& [% K/ d7 G: R6 [% i
  184.         }- X2 ~4 u1 E3 R( s* y/ H1 y3 E
  185.        
    ! g  B' c& n1 T8 \: g& f& U! L
  186.         else" o5 b! n  U  x
  187.                 return ERROR;
    # C& l; `& G0 X: P
  188.        
    3 p* O0 f; {! [/ R5 T7 a3 g
  189. }
    9 V; i; @  ]/ K1 y% b) t
  190. 0 a& a$ g* s; Z% K" w# K1 r

  191. 1 k# g' N7 f# E1 |
复制代码
8 t  T' D1 Z  [" w2 Y$ X8 [
3.main.c
$ f) [# Z) |  A( `
  1. #include "stm32f10x.h"9 P) Z7 ?+ L2 c* f/ Q& S
  2. #include "delay.h"
    2 u0 D8 w# E- l9 o  |6 _+ o
  3. #include "usart.h") n- `5 g( D: e% z/ U
  4. #include "dht11.h"
    9 x& l8 X6 u' f5 P

  5. ( d; s2 R% H0 j
  6. int main()# S8 \, h1 B- S0 I4 k% ^3 n& y
  7. {
    ! K% `' ^! ?; ~1 Q
  8.         DHT11_Data_TypeDef Dht_Data;# z' T# Z- B1 H1 M0 a3 j* S
  9.         char Temp_Str[ 10 ] = { 0 };8 w; H2 q. \. {% z0 r
  10.         char Hum_Str[ 10 ] = { 0 };
    1 P- q8 E9 P6 V8 [8 [* D
  11.         USART_Config();   //初始化串口
    5 U. d: o, j! ^' K) A
  12.         SysTick_Init();   //初始化系统定时器: R- I3 W6 g0 y6 k
  13.         printf("\r\n***Dht11 温湿度传感器实验***\r\n");* E$ [  }1 M( _, p* n
  14.         DHT11_Init();  //初始化DTT11的引脚
    5 D- k# z$ Q- J
  15.         while(1)
    ! m9 O3 P7 _6 b' R7 s8 _
  16.         {
    / W5 \1 x% A) b. w( c! B
  17.                         //调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息* L6 N5 v/ a% G' y4 M! r8 G

  18. + B3 a0 L- W8 ]5 N
  19.                 if(DHT11_Read_TempAndHumidity(&Dht_Data) == SUCCESS)1 i9 S4 u, ^2 @% l5 D, x
  20.                 {" J+ |  e# P! n2 n! L" c' R1 W
  21.                         sprintf(Temp_Str,"%d.%d",Dht_Data.temp_int,Dht_Data.temp_deci);# |; [" ~; w2 W, G
  22.                         sprintf(Hum_Str,"%d,%d",Dht_Data.humi_int,Dht_Data.humi_deci);" @% z! K  y! a4 S* r  f
  23.                         printf("温度数据为:%d.%d ℃\r\n",Dht_Data.temp_int,Dht_Data.temp_deci);! H: [6 q- a& o8 q2 t2 B
  24.                         printf("湿度数据为:%d.%d %RH\r\n",Dht_Data.humi_int,Dht_Data.humi_deci);
    ) V7 g" B4 x. I% r
  25.                 }
    5 r( i- n) x+ G, ^6 A+ S
  26.                 else
    / b1 k& P9 o- t" d2 D) u: {' |
  27.                 printf("error\r\n");
    ! F$ T  Q: S8 x, l" l
  28. " r% ~. x; A$ C+ q% G0 ~- a

  29. ; m& w+ V$ C( v. q  H
  30.         delay_ms(2000);
    $ t6 }5 _0 t& |. @
  31.         }
    ( C8 v; L. R! @; K& `6 m: k
  32. }, 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
3cce415f69ab42c9a24402a6c427c894.png # 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
收藏 评论0 发布时间:2023-2-5 18:50

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版