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

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

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

1 j- m3 j9 v1 f# P3 t
微信图片_20230701181746.png
- [" i% a  `8 K) A( U# W9 Q9 Y
根据以上数据,即可算出温度和湿度的值,计算方法如下:
湿度 = byte4.byte3
温度 = byte2.byte1
校验 = byte4 + byte3 + byte2 + byte1
, T/ F& O, n/ j
DHT11和单片机的一次通讯最大为3ms左右,建议主机连续读取时间间隔不要小于100ms,下面是DHT11的三种时序:

6 w" g- h: ]6 P$ q: \3 E/ W
⏩ 数据发送时序
首先主机发送开始信号,即拉低数据线保持t1(至少18ms)时间,接着拉高数据线t2(20 ~ 40us)时间;然后读取DHT11的响应,正常的话DHT11会拉低数据线并保持t3(40 ~ 50us)时间作为响应信号,接着DHT11拉高数据线并保持t4(40 ~ 50us)时间后,开始传输数据

* r6 N4 w# U% |$ a8 `1 j
微信图片_20230701181742.png

  ?. D% }* n- q4 E' w$ s
⏩ DHT11输出0时序

3 W% Y0 F8 ~* E3 Z0 r% J  H7 s
微信图片_20230701181739.png
: o$ T/ \: h( \! o8 A  n
⏩ DHT11输出1时序

7 Z, v2 L  a+ L+ Y
微信图片_20230701181736.png

1 X9 V- I; k' Q" Z0 V

& Z7 Y1 s' F' U0 y
2.硬件设计
0 y# V4 T" [/ i' K6 k- p
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值
指示灯D1
USART1串口
PG11
TIM7(提供us延时)

! d7 x7 F9 R/ W- }/ O: D

8 V# v1 N; h5 V
3.软件设计
3.1 STM32CubeMX设置

9 B! c  f9 [& [, O( B
➡️ RCC设置外接HSE,时钟设置为72M

8 B/ M8 y/ {% k! x7 ~: I' i
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

+ [3 o) F3 C% f- H" M& X
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
) ]( I  e+ A5 }$ W) a1 ?
➡️ PG11设置为GPIO推挽输出模式、上拉、高速

! N2 f  W) x& U# P5 I* H+ \
➡️ 激活TIM7,预分频因子设为72-1,向上计数,自动重载值为65535;因此计数器CNT_CLK = 1MHz,计数器周期为1us

- D8 E& q( n; o3 h8 r
微信图片_20230701181727.png

& {: t- ^3 Z! Y. @/ T! [9 \0 u
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
- _* e, w/ k; C% T4 h- N
3.2 MDK-ARM软件编程

' x! K! _" S7 z1 Y$ A" C* L( ~
➡️ 在tim.c文件下实现微秒延时(us)函数
  1. void delay_us(uint16_t us){
    . |1 z6 D1 W: x: {; Q/ j
  2.   uint16_t differ = 0xffff-us-5;
    % B; w5 P% `# [* B# X3 [
  3.   //设定TIM7计数器起始值                                " F8 D# z6 `: S2 R& S3 _- d
  4.   __HAL_TIM_SET_COUNTER(&htim7,differ);
    + a+ U6 {( X* H% b" O& X
  5.   //启动定时器        . A% _  i5 K1 k' U" R3 f+ l2 x
  6.   HAL_TIM_Base_Start(&htim7);                        2 g( \7 z9 f( @7 g* c5 ~5 j
  7.        
    % x6 v6 j0 C  q3 L1 O* @" N
  8.   while(differ < 0xffff-5){        //判断6 F+ [- ~& j+ Z7 P  W3 D
  9.     //查询计数器的计数值1 Z  r. S3 y% _# Q/ S/ v
  10.     differ = __HAL_TIM_GET_COUNTER(&htim7);               
    # v3 ]8 U* }$ |" v- J/ z
  11.   }
    5 ~6 H7 q+ f/ R; Q$ Z" J) u/ K  |; u
  12.   HAL_TIM_Base_Stop(&htim7);8 p5 o3 C) k8 r
  13. }
复制代码
. m) `  ~) g7 e* }, Y! d" D8 @
➡️ 创建DHT11温湿度传感器驱动文件DHT11.c 和相关头文件DHT11.h
  1. void DHT11_IO_IN(void){  //IO口方向设置为输入
    # n' w! f. S6 R
  2.   GPIO_InitTypeDef GPIO_InitStructure;2 ^: e7 R3 R- T2 y' L& ?% E0 k7 M' b
  3.   GPIO_InitStructure.Pin = GPIO_PIN_11;# B; h$ \& K! p
  4.   GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    # B8 L7 z& \& G' i0 a6 O
  5.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);1 f+ h- ~% V& A* ?0 w
  6. }
    + q- ?# s3 N# m' y: G  j
  7. . ^' Q3 I6 Z4 }0 ]
  8. void DHT11_IO_OUT(void){  //IO口方向设置为输出
    5 t& F' _2 D+ D' o9 m! Z
  9.   GPIO_InitTypeDef GPIO_InitStructure;" w' b( D8 W) X, u3 S5 k9 W
  10.   GPIO_InitStructure.Pin = GPIO_PIN_11;/ y, h" y3 P% C- [
  11.   GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;5 u  M: Y9 i1 `$ K/ g- s; E$ P
  12.   GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;. z/ R$ J$ l6 Z$ Q# w8 e! A
  13.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
    8 y' X* x% i6 }% y9 ]. w
  14. }
    8 B) x! Z: m- ?) i
  15. " Z9 c( ?+ W& t* i) Z
  16. void DHT11_Rst(void){                 ! M# L" d, k9 i* D/ Y
  17.   DHT11_IO_OUT();         //设置为输出
    & A3 R4 X- `$ Y9 s
  18.   DHT11_DQ_OUT_LOW;         //拉低! k1 {2 F# y4 u, Z
  19.   HAL_Delay(20);            //至少18ms5 Z0 U  C' t5 ~
  20.   DHT11_DQ_OUT_HIGH;         //拉高
    2 c9 l; ]3 a. u' d6 o0 H$ a
  21.   delay_us(30);             //至少20~40us! D+ F( ?$ z6 c- O1 }9 n# V) p1 W+ O
  22. }! x. r. D5 s, c+ `) {, l% K% F
  23. " Y( J$ }$ a& p! s" k0 V
  24. uint8_t DHT11_Check(void){   0 s/ G, I  i) \; l- ~! i) J
  25.   uint8_t retry=0;6 [/ n) Z# ]" R: M; r: {; X: s
  26.   DHT11_IO_IN();      # }+ H  ]- ]+ v- m& [) k2 x
  27.   while (DHT11_DQ_IN&&retry<100){ //拉低40~80us3 D* q7 W; X6 z" \* E/ Q% e# Y
  28.     retry++;
    7 D5 n: w; C* ~& r. B3 U# J1 ?; M$ ~
  29.     delay_us(1);
    . `, n( m, t3 y0 s4 h3 Y
  30.   };         8 V& F  u( k6 z+ i' ]) z6 [' V1 b
  31.   if(retry>=100)return 1;
    ( M; d- E" I& G# k2 V+ y
  32.   else retry=0;
    / O! z9 i2 ]# k6 n+ R( t0 J! ]8 U
  33.   while (!DHT11_DQ_IN&&retry<100){ //拉高40~80us5 s, A& u" f' r  v  F- {
  34.     retry++;0 X5 J$ t4 S' g
  35.     delay_us(1);
    . y7 J  w9 h: E9 k0 ]0 q
  36.   };' \, j. `( G' r6 s2 @
  37.   if(retry>=100)return 1;            
    : U8 |' }9 x" {3 u, R; W
  38.   return 0;        //检测到DHT11返回0
    ' |% `$ d2 f! i8 _% J0 {3 ~4 V: s
  39. }
    8 G- J/ W( Z; R8 M+ M8 R4 G7 x
  40. 9 r, f: y* S' ?3 V7 H+ B
  41. uint8_t DHT11_Read_Bit(void){
    ' |0 a. h& K" T
  42.   uint8_t retry=0;
    ; j( x8 e+ Z$ J5 ?7 v$ f3 I
  43.   while(DHT11_DQ_IN&&retry<100){//等待变为低电平
    ; x- u5 m- i! i0 ?3 H0 v$ B$ ]
  44.     retry++;
      Q0 k" B5 j+ S, p; `0 ?
  45.     delay_us(1);4 i5 N4 v5 g0 [0 L: U  _/ T  H
  46.   }
    ; j5 D; b( s0 b. ]" t1 N
  47.   retry=0;4 L& S+ N% h/ n0 X
  48.   while(!DHT11_DQ_IN&&retry<100){//等待变为高电平
      }2 ?9 s0 G' J' J# {5 R2 r
  49.     retry++;
    / W+ x9 a( C/ W: P& \6 `) y
  50.     delay_us(1);/ C6 [; d" _3 @! j
  51.   }- V1 G1 I, ~% Z+ c# M
  52.   delay_us(40);        //等待40us
    + q  U7 p# [: Q5 R; d
  53.   if(DHT11_DQ_IN)return 1;8 U3 F1 i, o: l
  54.   else return 0;                  
    7 {' {8 H- |( Y" [9 h2 E% m
  55. }+ z1 O0 h' Q, e  c5 U: n

  56. ) m, X$ ~) m' l0 _; X$ |
  57. uint8_t DHT11_Read_Byte(void){        - f1 a1 _9 j- a9 l
  58.   uint8_t i,dat;
    8 p2 c4 R- H1 z5 [- g- f+ R) T9 a
  59.   dat=0;
    ; l8 o8 |! S% Y8 j
  60.   for (i=0;i<8;i++){0 N- z* C: M/ Y9 N" B
  61.     dat<<=1;
    : J5 ]5 _2 B! m
  62.     dat|=DHT11_Read_Bit();& {$ D, D) O+ C3 K
  63.   }                                                    
    0 n% |7 M+ x3 N8 C$ ]
  64.   return dat;
    8 t0 u: n+ s; T, i1 R
  65. }
    3 R- f% G1 K/ q4 b. h$ x
  66. & n% i7 k: W$ ?) o4 O
  67. uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi){        
    + U( H4 w4 d' v$ @& [' e8 }# U$ B
  68.   uint8_t buf[5];
    * x) N& Q3 c' \0 C6 Z
  69.   uint8_t i;
    . d% m2 j/ k/ h2 Z- ]; J9 r$ r7 x' ~
  70.   DHT11_Rst();) h0 V! W  [+ C7 m3 i0 B; B- Y
  71.   if(DHT11_Check()==0){
    3 L+ E- C- x  J0 s
  72.     for(i=0;i<5;i++){
    9 c0 u6 p1 o' a# r+ q8 g/ L# V
  73.       buf[i]=DHT11_Read_Byte();5 ~5 d, q; y3 g
  74.     }
    1 }+ u7 G. l4 K1 o
  75.     if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){
    % c# a2 I! k, ^1 h% i7 G
  76.       *humi=(buf[0]<<8) + buf[1];( y! Z# N) `& {
  77.       *temp=(buf[2]<<8) + buf[3];
    0 {$ d% X- D$ ^: p
  78.     }
    * M0 @$ X$ [2 G5 W, y$ v  r
  79.   }else return 1;, i" m( v& u  M4 @% f2 V& u
  80.   return 0;            
    5 g0 z: w: ?- \9 a" B
  81. }
    7 f8 R7 ~) F9 z* K0 C+ C0 u  @4 k
  82.            
    ( L8 L1 P7 g7 Y/ N' L
  83. uint8_t DHT11_Init(void){
    ! d; h8 r' h' D: ]- i( O" b6 e
  84.   //PG11的初始化已经在cubemx中完成,可以忽略此段初始化代码
    # @0 q/ i2 k7 T% v, X3 Y
  85.   GPIO_InitTypeDef GPIO_Initure;        5 `/ q( A! \+ a+ C$ q
  86.   __HAL_RCC_GPIOG_CLK_ENABLE();                       
    + D" a( j3 \0 z+ ^$ }* u% H* e8 e0 g; L
  87.   GPIO_Initure.Pin=GPIO_PIN_11;           : E% B) l& Q* H% a
  88.   GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  6 M( L: k* I7 i4 A  J
  89.   GPIO_Initure.Pull=GPIO_PULLUP;         
    $ A# C* E$ @4 Y/ x* a& e$ t6 z9 N0 z, {
  90.   GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
    - ~; ^* [/ G. R3 Y
  91.   HAL_GPIO_Init(GPIOG,&GPIO_Initure);   
    1 C1 F7 _* D  O4 K
  92.   DHT11_Rst();, k; i8 C4 }' R1 Q8 h
  93.   return DHT11_Check();) ]& _( K8 H/ y7 A* T% N
  94. }
复制代码

. d, M+ n* ~6 Y* `9 n+ X
➡️ 在main.c文件下编写DHT11测试代码
  1. int main(void){
    " N; T/ |/ v7 m) [- i9 m: @
  2.   /* USER CODE BEGIN 1 */
    " h) v" T2 B" i, Z  U) T, k/ y7 y
  3.   uint16_t temperature;
    & \9 I5 h, A" j8 F( K+ v
  4.   uint16_t humidity;8 |$ b9 F, e% g3 f% R7 M$ M1 X) T9 H
  5.   /* USER CODE END 1 */, L. }# }6 Q4 j$ h+ ?! ]5 y* h
  6.   HAL_Init();
    + p4 a! C7 U5 z$ u$ m8 ]
  7.   SystemClock_Config();7 @  \+ p3 r: H- A6 l" s
  8.   MX_GPIO_Init();
    + x+ n# f' n* q. z7 k( J
  9.   MX_TIM7_Init();
    ( u9 Y/ ?- F& i5 d
  10.   MX_USART1_UART_Init();; j" f7 p! ?5 {/ w
  11.   /* USER CODE BEGIN 2 */
    6 c$ m  T0 @2 S1 v- \) d! g, A
  12.   while(DHT11_Init()){
    $ R. v# m: ]2 p1 Y' b- z
  13.     printf("DHT11 Checked failed!!!\r\n");
    . I. n- ?+ ]$ T) K5 }& E
  14.     HAL_Delay(500);
    7 |0 g, ?: p& H+ ~9 [3 V5 F) r9 g/ a+ y
  15.   }& Z, M7 j! R2 K% \8 ?' E
  16.   printf("DHT11 Checked Sucess!!!\r\n");( H8 R' g3 F4 g6 I, ^+ ~
  17.   /* USER CODE END 2 */1 D8 p: {/ H) F5 G( u( ?2 w
  18.   while (1){0 E9 K. [- q1 J$ @" `, S% \
  19.     DHT11_Read_Data(&temperature,&humidity);
    % E$ M4 c! j( y
  20.     printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);( T, J3 v- [7 u4 }7 N! g
  21.     printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);               
    3 @+ v& }5 C& J
  22.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    % T+ J/ u( s" g. A" l: T
  23.     HAL_Delay(500);
    4 R1 W/ |/ \8 y4 y2 u/ A' r
  24.   }* {- h2 F4 M- e3 K
  25. }
复制代码
3 C0 m* ?# T1 H: a
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,串口不断打印出当前温湿度值。串口输出如下信息:
DHT11 Checked Sucess!!!
DHT11 Temperature = 28.20 degree
DHT11 Humidity = 30.21%
转载自: 嵌入式攻城狮# c' n5 ~/ g, Y
如有侵权请联系删除
/ T$ O$ R7 o# m4 Y0 z! D8 c$ i
9 g$ J* O# h  S# T8 Z7 j9 O0 |0 v1 r0 Y' T0 v; i
收藏 评论0 发布时间:2023-7-1 18:18

举报

0个回答

所属标签

相似技术帖

官网相关资源

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