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

基于STM32的数字温湿度传感器之驱动DHT11

[复制链接]
攻城狮Melo 发布时间:2023-3-18 14:22
DHT11模块简介) q5 |. H4 R/ j4 L& b
DHT11数字温湿度传感器,用来测量环境的温度和湿度,而且传输的数据是数字信号,这与DS18B20传输的模拟采集的数据不一样,相比DS18B20而言DHT11的数据采集的处理更加精确,而且驱动也更加方便。! P; D$ M, z- }* H3 e. H, i
DHT11传感器包括一个电阻式测湿元件和一个NTC测温元件,而且传感器中嵌入一个8位单片机。传感元件测量到数据后经过内嵌MCU处理后,能够直接输出处理好的数据。
: g& C) @1 K) d3 m4 b2 fDHT11与单片机之间采用单总线通信,只需要初始化一个I/O口即可实现温湿度的实时测量。+ h, ~- {! @. T, G4 Z. z
其相关参数如下:
7 H- J2 e# m; ^+ s: u) L/ ^
8 M" G! a0 J! N4 a* z
201911241037112.png
: Q$ J) z- D2 \; ?0 v; f0 {/ X% U* J) y( J! R/ t
DHT11数据传输
: _. d. g# j3 A) [/ p# s
DHT11数据传输是单总线通信方式,即通过一个IO口完成数据的双向输入输出,DHT11每一次向单片机传输数据是传输40Bit的数据包,40Bit的数据包中包含如下内容:
2 ]' v/ t) A- o7 ^(32-39)湿度的整数部分, C8 H6 u. q+ Y  @$ n5 M5 j
(24-31)湿度的小数部分
  Q" ~* M) @8 E* Q(16-23)温度的整数部分+ l% X% N3 a2 p0 {6 Y, `2 Y
(8-15)温度的小数部分7 k+ \# A  G4 A5 z0 C. [
(0-7)数据校验部分,前四部分的和
  J9 x4 J- ?# M+ e
例如:
, W' K. P4 \8 ^9 V7 D& O
# u% `4 q# f0 ]( W7 o' X
2019112410431168.png
- V9 o4 m8 V7 Z4 Q7 m

) k+ ]# J+ w: s5 L湿度为:45.0
; w5 c7 n# B) G% r' u# ?" d) l7 ~温度为:28.0
1 c" j/ O, C& w( ~  H: `校验为:73=45+28(数据正确)0 n5 d1 v) I3 m7 j/ c
2 y0 I' j6 y, _

7 h* W; l6 G2 b: @6 H, L$ Q& I( tDHT11通信时序
# C0 [0 ]0 F) N) a( i! M6 ^
由于DHT11和单片机是单总线通信的,所以数据的双向传输就依靠严格的时序规定了,DHT11和单片机通信的时序有三部分:3 C! `3 S2 l8 a8 i# w
单片机向DHT11发送复位信号
7 \% y. T8 @! _DHT11响应单片机的信号& N% j# v7 ]/ j, V; ]2 J5 w
DHT11向单片机传输数据包% p' G6 p* h9 R
8 a  e% T0 s9 O  M
总的时序图如示:
0 e( B1 M1 O# ?7 P
! ~# L! _: e: d0 e& p" u+ g2 P
20191124105804147.png
" w1 L1 B+ k3 B
% P' P# \) F% \$ F3 a+ E
第一步:发送复位信号,此时引脚应模式为推挽输出。拉低数据线,持续t1(至少18ms)时间;然后拉高数据线,持续t2(20~40us)时间。  X0 C0 {, e5 l  C
第二步:读取相应,此时引脚应模式为浮空输入。DHT11会先拉低数据线,持续t3(40~50us)时间,作为相应信号;然后DHT11拉高数据线,持续t4(40 ~50us)时间,开始传输数据包。4 ^( q% y& c, ]7 v( l8 P) ~
第三步:传输数据包。传输“1”时,12 ~14us低电平+116 ~118us高电平;传输“0”时,12 ~14us低电平+26 ~28us高电平。# ?4 n+ F4 ^( X+ F

  b1 l- o* c! y) x3 J& c3 o/ P: ?
20191124110636317.png
) D$ ~9 @4 k& K3 F. `  C, A% w) n( D6 p9 _+ ~2 M8 ^( G

* z+ `! L1 D: X- X这三步就完成了一次完整的数据传输,然后就单片机是对接收到的数据包进行处理显示就好了。: {! W1 A  l- Y  g) X2 O" }
9 ]" B# i5 V; @0 u" p' l

8 l) l$ {( X0 r* g% y代码实现
/ C+ A. K5 f) c: b驱动代码主要实现如下几个模块:
2 s) p; m9 ]; G9 i# x$ s& c- t" k相关引脚初始化; v$ t% C% m1 \  g, \# V. d% ]
复位模块- T) d: P2 B$ E6 r
判断响应模块4 M9 z, Q( t- z
读取数据包模块- B1 g! _+ E9 A$ I# s! G
显示模块. w( {6 P5 u' h, [5 ~+ O7 [

; m: a2 n2 G" q) Q6 |
相关引脚初始化
. F9 ~7 E! y# F  m0 C- d$ _由于是一个IO口,要满足输出和检测电平,所以我写了俩个函数来切换引脚的模式,可以使引脚在推挽输出和浮空输入之间切换:
: E6 A3 i8 G& B+ V+ I
  1. /* 相关引脚的配置,DHT是单通道通信,所以一个引脚就够了 */
    . p% ~. s( `6 R0 `4 ?/ c
  2. void DHT_GPIO_Config_Output( void )( }% @1 i& S- U% ~/ o
  3. {$ G4 b7 P( `0 v% \- s
  4.         GPIO_InitTypeDef GPIO_InitStruct;       
    5 h8 L) z# r& ^: k
  5.        
    0 t" _8 X: d$ m. L9 w0 G, @
  6.         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    / n8 F$ i$ W# Z8 J" n( W  F
  7.         GPIO_InitStruct.GPIO_Pin = DHT_PIN;
    & d% ^7 ^4 T8 A
  8.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;1 ~) E0 \2 x9 p; A) ~3 j% e
  9.         GPIO_Init(DHT_PORT, &GPIO_InitStruct);1 ^% H; O; M( O
  10. }/ q5 p& B  w) X2 `

  11. - O% x0 m8 ^! W0 E
  12. /* 同一个引脚 要在输入和输出的时候进行切换引脚模式 */
    * I4 O; f, f! ?' b
  13. void DHT_GPIO_Config_Input( void )
    8 Q& H$ K* G: v# V/ w  t
  14. {( U% L- b& I' }$ t* f& `) b. [! a
  15.         GPIO_InitTypeDef GPIO_InitStruct;
    : O) h$ C8 h( K( A+ r  w5 V, G
  16.         : X3 K0 g$ }0 b
  17.         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;5 A2 }3 p: Y7 j7 n- x
  18.         GPIO_InitStruct.GPIO_Pin = DHT_PIN;
    : S$ ^- ]' y3 l& R2 R
  19.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    * a. [# h" W) h  h* @
  20.         GPIO_Init(DHT_PORT, &GPIO_InitStruct);( j# P! j& V) a* K
  21. }
    : N/ t0 l5 Z$ w' o0 G( _
复制代码

6 o' B. |: o* s: B  w) \在初始化的时候会开启时钟,所以这俩个模块就不用开启时钟
% h8 W# b  a5 \; ?

' Z" ~6 ~! J, }8 o9 c: }* C7 W复位模块
; x. F; Z: Z+ K% t1 f0 S
  1. void DHT11_Rst( void ); Y8 [/ V5 L( X. a' D( B
  2. {
    # e4 X8 t: a$ h7 G9 ]8 Y6 E
  3.         DHT_GPIO_Config_Output();
    # N& L3 U5 E( k; v$ d  a$ |4 l
  4.         DHT11_L;
    0 u* K( m7 L7 H+ {7 }) g
  5.         Delay_ms( 20 );
    0 D/ S6 A2 j- _9 c# N& _) H0 ?/ c
  6.         DHT11_H;
    4 t8 L3 l5 D& _4 F8 I: W+ o
  7.         Delay_us( 30 );. Y- N6 q6 j9 _' Z: H* y2 M( V2 o/ }7 X
  8. }
    , g! S( ~+ c( n& h- h7 ~
复制代码
6 {' z& e  S3 J  L) a% i
判断响应模块
! i& `& e4 Z* h1 T
  1. uint8_t DHT11_Check( void )
    2 Z# e! t' @$ y9 ^9 j8 g
  2. {
    ! c& N3 O2 P2 r. s& Z; g
  3.         uint8_t t;9 u9 y$ y# Z1 }3 v4 W) b9 Y
  4.         /* 浮空输入,判断引脚输入电平 */
    4 w5 s) j/ r7 G; p  P
  5.         DHT_GPIO_Config_Input();) W' S; x2 j5 h# w( J( K) W
  6.         while( DHT11_Value_L && t<100 )
    * ~& A; c2 r, A9 ]* {8 ]
  7.         {: w9 Q- @* I' t
  8.                 t++;
    9 y" `& \7 A1 H
  9.                 Delay_us(1);* }+ @5 k& n: K- Y' f
  10.         }
    1 E) e& D- `0 Y3 ^7 C8 A( B
  11.         if( t>100 ) return 1;+ T1 T2 e7 W1 `  Q. A0 \
  12.         t=0;
    1 }; j; t* n3 a, n, O6 j, z
  13.         while( DHT11_Value_H && t<100 )% O5 w4 [6 c, w2 U8 q0 _- D. A6 K
  14.         {# z( K! t$ F- o$ A: x# D
  15.                 t++;7 J$ D! l( L5 r7 q9 a
  16.                 Delay_us(1);
    0 ~; Z% w* H  w2 x: \
  17.         }6 n( F- |2 V. g, T
  18.         if( t>100 ) return 1;# _5 m) G3 o% U$ a, p1 \4 [
  19.         return 0;
    & u) r$ a; `& O. l; n' h
  20. }
    3 K* _) ?; V% N" e
复制代码
5 ]0 L$ L8 Z) U- Z. z
读取数据包模块' J- H& q" v6 w# o/ C% B
  1. void DHT11_Read_Data( uint8_t *temp, uint8_t *humi )
    ! H. u- s8 g# R/ W  g$ C
  2. {' j2 N( c5 f1 r7 m
  3.         uint8_t i,t;
    - w1 B3 N% p. s: D5 a0 g3 W- C
  4.         uint9_t data[5];2 J, |: P. d  W7 h$ B' @& i
  5.         DHT_GPIO_Config_Input();" N! B4 L9 s# X. e
  6.         /* 执行40次读取位数据,data指向数据包 */8 K* U0 D/ ~2 g+ V/ s
  7.         for( i=0;i<40;i++ ): T0 C6 ^" i" b  t0 o: T
  8.         {7 l. i) c8 ^1 Y( G) ^
  9.                 /* 开始低电平 */! ]; J: w+ G5 Y4 E; H
  10.                 while( DHT11_Value_L && t<100 )
    1 [& v" U4 c6 V
  11.                 {& Z1 @+ l" x, q7 A* O. t9 O
  12.                         t++;  g6 O; C/ ~# v, u# i0 G
  13.                         Delay_us(1);
    9 X0 d8 |. ^: Q4 L0 T& n
  14.                 }' b$ E1 {' Y" I4 o8 P8 C
  15.                 t=0;5 D( u4 g: |# U
  16.                 /* 开始高电平 */
    6 m( g; |7 \. x$ }; {2 U7 Q: ~
  17.                 while( DHT11_Value_H && t<100 )2 E" u: m& F+ [2 m" F8 G
  18.                 {
    6 W5 P( \# v: l/ v* q& w" U
  19.                         t++;
    $ h; v0 R; \7 C' t4 s
  20.                         Delay_us(1);
    1 @+ ~9 ]- e1 b" s+ O
  21.                 }
    8 l! X/ w7 X! p7 |* }* w
  22.                 Delay_us(40);/ Y$ ?0 n( m0 l4 ~; i, r* _' ]
  23.                 /* 判断高电平持续时间 */
    : i% i: @+ m8 t  ~8 m8 e
  24.                 if( DHT11_Value_H )  ]2 v7 a4 `# z& K) Y
  25.                 {
    : I+ |+ [: c# S3 h* e4 p* O5 q' K
  26.                         data[i/8] |= 0x01;
    * }3 B7 ?4 q% J8 r8 o
  27.                         data[i/8] = data[i/8]<<(i%8);2 j- L0 U: T" `* l4 J6 e
  28.                 }
    % ?* c- }3 d2 P: Z
  29.                 else' _* I  C. g# O" B3 b: s
  30.                         data[i/8] = data[i/8]<<(i%8);5 G) `* c2 i/ y* ~! O
  31.                        
    / d. y" d) X- q. C6 H
  32.         }' E3 `( I/ u, p6 `6 E# y
  33.         /* 将数据地址传出去 */
    6 X8 X0 M7 g, N7 M. |, G
  34.         *humi = data[0];
      l: B* F4 q& ^, F3 l8 ?/ w: q, d
  35.         *temp = data[2];& A& T) x* p- W
  36. }
    + Q. q+ M/ I' c5 g. P
复制代码

4 D- ~/ i" y4 F' M只是大体总结了一下,有不足之处还望各位朋友指出/ D# v7 B1 q0 g: F/ S
————————————————( S. u& t( h2 {+ i) U( a
版权声明:Aspirant-GQ
8 _' V( Z& v' D; h( R2 Y1 X* ?如有侵权请联系删除
% o1 S' i! o( R' h2 Y0 @. W
, X, F0 @+ `4 u/ M" v9 L( T
! O3 G0 [! H: s) H( B7 e  M' B: I* B' o6 e* R6 u, ?
赞 收藏 评论0 发布时间:2023-3-18 14:22

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版