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

基于STM32CubeMX DHT11温湿度传感器经验分享

[复制链接]
攻城狮Melo 发布时间:2023-7-1 18:18
1.DHT11简介
DHT11是一款温湿度一体化的数字传感器,该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机连接。通过单片机微处理器简单的电路连接就能够实时的采集湿度和温度。DHT11与STM32之间能采用简单的单总线进行通讯,仅需一个IO口。传感器内部温度和湿度数据40个bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。
DHT11采用单总线数据格式,即单个数据引脚端口完成输入输出双向传输。其数据包由5个字节(40Bit)组成。数据分小数和整数部分,一次完整的数据传输为40bit,高位先出。数据格式如下图示

; a/ F7 \) L3 F5 r  {7 t
微信图片_20230701181746.png
1 p6 n4 F- T1 N7 P7 n# B9 s
根据以上数据,即可算出温度和湿度的值,计算方法如下:
湿度 = byte4.byte3
温度 = byte2.byte1
校验 = byte4 + byte3 + byte2 + byte1
0 ~/ \$ V0 M  E, D+ z$ `
DHT11和单片机的一次通讯最大为3ms左右,建议主机连续读取时间间隔不要小于100ms,下面是DHT11的三种时序:
1 Y! h1 a+ C& `" b9 h: h
⏩ 数据发送时序
首先主机发送开始信号,即拉低数据线保持t1(至少18ms)时间,接着拉高数据线t2(20 ~ 40us)时间;然后读取DHT11的响应,正常的话DHT11会拉低数据线并保持t3(40 ~ 50us)时间作为响应信号,接着DHT11拉高数据线并保持t4(40 ~ 50us)时间后,开始传输数据
% z! F( f8 J: f9 }
微信图片_20230701181742.png
( c, n! \# G2 J5 \
⏩ DHT11输出0时序
8 v3 F- A; @2 W# z) o8 Q
微信图片_20230701181739.png

# C& P9 H. {3 K: {5 D
⏩ DHT11输出1时序
: s; x5 y% u4 t, W
微信图片_20230701181736.png
" i0 x7 |: ~) p. v/ n; J0 _
; _- M2 O2 M# ]. B/ T3 T- J0 k6 U  ]
2.硬件设计

1 f- T) H: Y! S8 Y. o/ J  a
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值
指示灯D1
USART1串口
PG11
TIM7(提供us延时)

: o9 z) w) \4 w+ M1 w! H6 L
) T3 Q1 p; w( ~5 l$ W! {
3.软件设计
3.1 STM32CubeMX设置

) x  ~9 k4 i) u
➡️ RCC设置外接HSE,时钟设置为72M

/ ~3 ]1 n9 ^1 X% L. {  ~1 H
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

% s5 C3 p2 Y7 ~; p+ h$ a
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
' z: _% s9 J  j. u& ^+ e0 R5 V
➡️ PG11设置为GPIO推挽输出模式、上拉、高速
$ a$ S$ I8 Z, V, ^1 O
➡️ 激活TIM7,预分频因子设为72-1,向上计数,自动重载值为65535;因此计数器CNT_CLK = 1MHz,计数器周期为1us

1 X* M. P' V, r+ H& I
微信图片_20230701181727.png
. u+ c. t8 |& H) S; ]
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

" l$ b( v) |* N  `( ]7 P
3.2 MDK-ARM软件编程
3 d6 T( ]7 K+ D4 [; q" ~
➡️ 在tim.c文件下实现微秒延时(us)函数
  1. void delay_us(uint16_t us){
    ) C6 ?9 ?5 g; Z" r
  2.   uint16_t differ = 0xffff-us-5;9 L3 a9 u" z5 A) o, n. a
  3.   //设定TIM7计数器起始值                                * X9 N4 q) L8 n
  4.   __HAL_TIM_SET_COUNTER(&htim7,differ);
    ' l9 S8 k2 X# M( f, G% g+ H* H
  5.   //启动定时器        0 v" ]3 {  {# j4 E
  6.   HAL_TIM_Base_Start(&htim7);                        + l3 j/ n6 u5 x; F- q1 E" Y3 b
  7.         # y: l6 f! R4 P( K/ f4 X9 H
  8.   while(differ < 0xffff-5){        //判断. `6 u5 X4 @# q& o' y+ k* E5 Q
  9.     //查询计数器的计数值( {! p6 A! x0 [# h
  10.     differ = __HAL_TIM_GET_COUNTER(&htim7);                " i- v2 G, c- `( r' f
  11.   }
    / a: v" W' z- Y
  12.   HAL_TIM_Base_Stop(&htim7);
    ) ~% K1 G5 a" ~
  13. }
复制代码

4 ^4 e) h4 c" F% s5 f! A( K
➡️ 创建DHT11温湿度传感器驱动文件DHT11.c 和相关头文件DHT11.h
  1. void DHT11_IO_IN(void){  //IO口方向设置为输入
    - F  w* N) ?3 e
  2.   GPIO_InitTypeDef GPIO_InitStructure;1 P, p* M# k: i7 E
  3.   GPIO_InitStructure.Pin = GPIO_PIN_11;+ ?, X- R0 l$ G& r
  4.   GPIO_InitStructure.Mode = GPIO_MODE_INPUT;: r0 v1 O! O. l  Z
  5.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);' n. A0 w! n9 a$ ^. R) F7 A
  6. }
    & V* Z; v# N* L
  7. 4 A  P5 A7 t% V8 Z
  8. void DHT11_IO_OUT(void){  //IO口方向设置为输出
    % j( @' F% A6 D3 @, V$ v6 \
  9.   GPIO_InitTypeDef GPIO_InitStructure;" }+ F8 ]8 r$ d6 i3 v
  10.   GPIO_InitStructure.Pin = GPIO_PIN_11;
    $ @1 z& Y- i  }! Z5 A
  11.   GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;9 {9 m! }) @9 C4 T; d4 |
  12.   GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;6 H0 y$ i# ~: `: H4 _. E1 G. n
  13.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
    ! ^, U0 I2 H, E0 S
  14. }
    " f8 q" ^+ N2 B$ c1 u8 d* G

  15. " G9 ]$ v; }7 g2 u# X* a
  16. void DHT11_Rst(void){                 
    % {" j  F9 ]" N2 k8 i( J
  17.   DHT11_IO_OUT();         //设置为输出( l7 L, g" ]" o$ {& Q1 ]& P
  18.   DHT11_DQ_OUT_LOW;         //拉低1 h2 c+ g% j3 z* ^! h) z. c
  19.   HAL_Delay(20);            //至少18ms% E3 Z$ b( p" v3 h, [
  20.   DHT11_DQ_OUT_HIGH;         //拉高
      x7 ~7 P8 h3 I/ Z$ z* V* [( {0 F, P
  21.   delay_us(30);             //至少20~40us2 X/ m  ?% T8 S
  22. }
    ; y; ?, p; ]. z% l$ h

  23. ! F5 y( _% q9 m, ?
  24. uint8_t DHT11_Check(void){   
    ' l6 n- I5 E. g' r) H
  25.   uint8_t retry=0;
    , J) w8 G4 ~( J% V
  26.   DHT11_IO_IN();      , ^, g+ Y5 Q: w$ S  X+ f+ }
  27.   while (DHT11_DQ_IN&&retry<100){ //拉低40~80us
    % |' h/ c2 G0 {; Z$ V
  28.     retry++;
    1 P0 z. ], F9 k/ Z+ i
  29.     delay_us(1);1 b$ C2 n0 B1 H* l
  30.   };         
    8 m% r' ?+ k3 g) \5 t% n
  31.   if(retry>=100)return 1;3 n/ C8 I5 u- b: T0 e6 `
  32.   else retry=0;
    ( A7 X" J% Y3 k+ W
  33.   while (!DHT11_DQ_IN&&retry<100){ //拉高40~80us! U& q& G) e7 C. Y
  34.     retry++;  T. f+ L2 g6 G' i9 v0 X2 V
  35.     delay_us(1);3 e8 [& }; y* b  ^8 k6 R- ?* f0 x& W
  36.   };
    3 s+ z/ R3 f/ b  |
  37.   if(retry>=100)return 1;            5 e. W. P) Z- ]+ |5 ^
  38.   return 0;        //检测到DHT11返回0! P: B% _0 r0 |$ q8 v
  39. }8 n* x/ }& [( H1 e$ S
  40. 7 L! h; M7 f* a4 \! O1 L
  41. uint8_t DHT11_Read_Bit(void){* l- T, D0 E" u! |8 k- d% F' r
  42.   uint8_t retry=0;
    ' R3 x+ R' E# @; i. o3 B9 \
  43.   while(DHT11_DQ_IN&&retry<100){//等待变为低电平$ ^) l. p* k  X( w
  44.     retry++;9 }1 D. ?% P! j/ p. P8 ?
  45.     delay_us(1);
    5 W! D& S. a9 g
  46.   }# T) b; V' \: _0 h/ h
  47.   retry=0;
    9 S( O$ s  Z! V% ]8 @, J: Y
  48.   while(!DHT11_DQ_IN&&retry<100){//等待变为高电平
    ; B, n( u) @  a1 p8 G' z
  49.     retry++;
    , _1 A% n1 \! W" T
  50.     delay_us(1);' z" ^% z( u( w* i4 Y4 t+ t8 t
  51.   }9 x; B3 F) ?, G  g, }
  52.   delay_us(40);        //等待40us( n  T' b7 x) f4 T. C
  53.   if(DHT11_DQ_IN)return 1;
    0 l% L: z2 G( a6 p
  54.   else return 0;                   / D/ Y% j0 ?# e9 J
  55. }6 @0 V" P. o' |. v- G0 i( |
  56. * U. g1 h  O- L! r
  57. uint8_t DHT11_Read_Byte(void){        9 c0 p6 B% S  ?+ {
  58.   uint8_t i,dat;
    * p( [, v8 k/ X( T4 \
  59.   dat=0;+ t. t$ B( [8 N- M
  60.   for (i=0;i<8;i++){5 G: O/ h# j" J
  61.     dat<<=1; # n- [! l8 u* k0 {& n. k: k: ?
  62.     dat|=DHT11_Read_Bit();9 o" v/ O9 R8 H
  63.   }                                                    # g% i* b: w$ J* o- h
  64.   return dat;
    * `* k/ e% X1 t* u  ]$ G% x0 T! E
  65. }
    8 u, M" ^( }! l3 U, I

  66. ! V/ A1 A% w- M# k; h
  67. uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi){        
    ( L; i5 F; Y; T- A: b+ L
  68.   uint8_t buf[5];
    ; h7 r6 v( B& ~. L: c/ n4 V" j/ ?; p
  69.   uint8_t i;
    4 U' j# ^, o$ |& {
  70.   DHT11_Rst();
    8 ?8 {; z) ]' J; V3 f
  71.   if(DHT11_Check()==0){3 {+ c- M& n' `1 g: }
  72.     for(i=0;i<5;i++){' t& T+ K9 B( ?+ _) V' j
  73.       buf[i]=DHT11_Read_Byte();
    4 a4 R5 }3 U& ]/ C) E! }
  74.     }
    % ]) [. T  i+ h% M. q, D4 J
  75.     if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){
    & \& w1 }1 L8 M. G; {
  76.       *humi=(buf[0]<<8) + buf[1];! q+ Y  s5 E% `- i) z
  77.       *temp=(buf[2]<<8) + buf[3];7 V5 S6 ]6 S! y  W+ @
  78.     }- B5 t8 H) A; u' W
  79.   }else return 1;
      `: W) s6 d3 z+ l* b( n" G
  80.   return 0;            
    3 `9 J2 \( L( u, V6 _* P, _
  81. }- t" i' Z! x9 ~- [/ c5 T
  82.            - x7 C1 |  G9 M4 [% h) X- q6 ~' \
  83. uint8_t DHT11_Init(void){/ _7 z0 V$ e5 I5 D$ J! L
  84.   //PG11的初始化已经在cubemx中完成,可以忽略此段初始化代码% G' M: S- t( E# v6 v8 U" V9 `
  85.   GPIO_InitTypeDef GPIO_Initure;       
    ) ^$ D# H7 \. ?. d. |* L
  86.   __HAL_RCC_GPIOG_CLK_ENABLE();                        , z) b5 m5 c1 j) R1 b" J
  87.   GPIO_Initure.Pin=GPIO_PIN_11;           
    , q) L  F0 F$ A! Z! z! \
  88.   GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  , ~' F5 a, l. u
  89.   GPIO_Initure.Pull=GPIO_PULLUP;         
    / X3 a- s: `" @
  90.   GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
    : }5 n4 j8 V, i) o& ?
  91.   HAL_GPIO_Init(GPIOG,&GPIO_Initure);   
    5 o) z: y$ m- l1 R! ?) ~1 H
  92.   DHT11_Rst();
    , X! a, v, R+ d$ W# U
  93.   return DHT11_Check();, R8 J2 O0 O' l+ y3 Y; V5 l8 j7 j4 k
  94. }
复制代码

, Y! s2 h5 _! N: G2 `5 o# x
➡️ 在main.c文件下编写DHT11测试代码
  1. int main(void){
      `: z: ?1 e( n6 X9 z- c8 O
  2.   /* USER CODE BEGIN 1 */
    7 i! ]3 R$ i0 ~" C( }* h4 C
  3.   uint16_t temperature;3 C0 t- C3 B# V( ?
  4.   uint16_t humidity;8 |; T& H* C. O0 V
  5.   /* USER CODE END 1 */# b" @8 V9 r+ O( o4 B8 t2 E
  6.   HAL_Init();; G& R* B9 d7 o" R3 ~8 ]/ T" q, }
  7.   SystemClock_Config();% D! B" m) z5 _( S- M
  8.   MX_GPIO_Init();
    # {7 ^" B3 m+ {" M- A1 d1 a
  9.   MX_TIM7_Init();4 x$ c5 Q5 C9 O) K& E3 C! y& t, I
  10.   MX_USART1_UART_Init();
    % F6 T  ?5 R! u/ q- h/ X
  11.   /* USER CODE BEGIN 2 */
    % Y3 O$ A9 s" r# P. m3 q
  12.   while(DHT11_Init()){5 r& z8 ?7 d2 [7 D+ b4 ^. v6 {
  13.     printf("DHT11 Checked failed!!!\r\n");
    ' k) M$ `9 O) h+ M
  14.     HAL_Delay(500);! W  p+ e3 Z8 }0 t0 [& A4 s# `
  15.   }7 @5 h" P# F2 Z% {1 T, P/ `, h9 q0 H4 ]
  16.   printf("DHT11 Checked Sucess!!!\r\n");& r. `) I+ \( p) |
  17.   /* USER CODE END 2 */& t, g3 q" x3 z% U0 O
  18.   while (1){
    6 m% g7 W% P. }5 v) B
  19.     DHT11_Read_Data(&temperature,&humidity);
    1 h4 ^9 K* A% H* u9 A& F
  20.     printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);
    & y. f/ U3 h3 [$ h. C9 c
  21.     printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);               
    # H: ?" R% f- t6 s2 E7 {
  22.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    ; R0 b7 o. \* i! G
  23.     HAL_Delay(500);/ z# p) {- _3 \, j0 t) n3 m
  24.   }) }; c6 ^, X$ ~; Q; x/ F: z
  25. }
复制代码

6 p: b! e$ v/ F$ l1 D) u5 F7 J
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,串口不断打印出当前温湿度值。串口输出如下信息:
DHT11 Checked Sucess!!!
DHT11 Temperature = 28.20 degree
DHT11 Humidity = 30.21%
转载自: 嵌入式攻城狮( M; u  C/ }6 B; D
如有侵权请联系删除7 I! H5 w# ^9 T# x; I. d( D2 z: d+ B

8 e0 G' `* S1 e+ ]& _: h( U* d$ O6 H& n2 N4 j% x0 |
收藏 评论0 发布时间:2023-7-1 18:18

举报

0个回答

所属标签

相似技术帖

官网相关资源

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