锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

STM8单片机读取DHT11温湿度传感器

时间:2022-11-11 12:00:00 频率温湿度传感器

DHT11是一款温湿度传感器,也是使用一根总线来驱动,使用方法和ds18b20温度传感器非常相似。

  • 供电电压 3.3~5.5V DC
  • 测量范围 湿度5% ~ 95%RH, 温度-20℃ ~ 60℃
  • 测量精度 湿度±5%RH, 温度±2℃
  • 分 辨 率 湿度1%RH, 温度0.1℃

如下所示
image.png
引脚顺序为1、2、3、4,引脚功能如下:

1 Vcc 供电引脚 供电范围 3.5V to 5.5V
2 Data 输出温度和湿度值
3 NC 不使用,使用时悬空即可。
4 Ground 接地

典型应用电路如下:

??由于单总线在通信时的自由状态下电平较高,因此外部应在2脚上连接一个上拉电阻,因此当总线上没有数据传输时,数据引脚的电平将被外部上拉电阻强制设置为高电平。

通过单总线读取数据分为三个步骤:

  1. 主机发送请求指令
  2. 返回相应的指令
  3. 主机开始从机器上读取数据

1.请求指令:
?当主机发送请求指令时,需要将总线至少降低18ms,然后释放总线40us。
2.响应指令
?当传感器检测到主机的请求指令时,它会向主机发送响应指令,告诉主机通信已经成功。传感器返回的响应指令是 54us低电平,80us高电平。


3.读取数据
?当传感器发送响应指令时,将发送40bit的数据,8个bit对于一个数据,共有五个数据,包括当前的温度和湿度数据。前两个数据是湿度数据的整数和小数。接下来的两个数据是温度数据的整数和小数。最后一个数据是前四个数据的验证和验证。

数据的整体格式为8bit湿度数据 8bit湿度小数据 8bi温度整数据 8bit温度小数据 8bit校验和”

数据传输时,发送的数据是0还是1,代表高低电平的时间长短。

??? Bit ‘0’ : ~54uS 低电平 和 ~24uS 高电平

??? Bit ‘1’ : ~54uS 低电平 和 ~70uS 高电平


结束标志:

数据传输完成后,传感器将总线降低54us,然后释放总线,代表数据传输结束,传感器进入睡眠模式,等待下一个请求信号再次醒来。

一次读取数据的完整时序图如下:

首先MCU发送请求命令,然后等待传感器响应。传感器响应完成后,将发送40bit数据,然后发送结束标志。然后自动进入睡眠模式,等待MCU下次唤醒。
时序搞清楚后,下面就可以开始编写代码了。

??代码如下:

#include "dht11.h" #include "stm8s103f3p.h" #include "delay.h" //IO口操作 _Bool  DHT11_DQ_OUT @PD_ODR:3; _Bool  DHT11_DQ_IN  @PD_IDR:3; //PD3 方向设置 void DHT11_IO_IN(void) { 
            PD_DDR&=~(1<<3);    //输入 PD3     PD_CR1|=(1<<3);     // } void DHT11_IO_OUT(void) { 
            PD_DDR|=(1<<3);     //输出 PD3     PD_CR1|=(1<<3)
      
       ; 
       // 
       } 
       //发送起始信号 低电平18ms 
       void 
       DHT11_Rst
       (
       void
       ) 
       { 
         
       DHT11_IO_OUT
       (
       )
       ; 
       //设置为输出  DHT11_DQ_OUT
       =
       0
       ; 
       //拉低DQ 
       delay_ms
       (
       20
       )
       ; 
       //拉低至少18ms DHT11_DQ_OUT
       =
       1
       ; 
       //置高DQ 
       delay_us
       (
       30
       )
       ; 
       //主机拉高20--40us 
       } 
       //等待DHT11的回应 
       //返回1:未检测到DHT11的存在 
       //返回0:存在 
       unsigned 
       char 
       DHT11_Check
       (
       void
       ) 
       { 
         
       //DHT输出80us低电平,作为应答信号 
       //DHT输出80us高电平,通知处理器准备接收数据 
       unsigned 
       char retry
       =
       0
       ; 
       DHT11_IO_IN
       (
       )
       ;
       //SET INPUT  
       while 
       (
       !DHT11_DQ_IN
       &&retry
       <
       100
       )
       //DHT11会拉低40~80us 
       { 
         retry
       ++
       ; 
       delay_us
       (
       1
       )
       ; 
       }
       ; 
       if
       (retry
       >=
       100
       )
       return 
       1
       ; 
       else retry
       =
       0
       ; 
       while 
       (DHT11_DQ_IN
       &&retry
       <
       100
       )
       //DHT11拉低后会再次拉高40~80us 
       { 
         retry
       ++
       ; 
       delay_us
       (
       1
       )
       ; 
       }
       ; 
       if
       (retry
       >=
       100
       )
       return 
       1
       ; 
       return 
       0
       ; 
       } 
       //从DHT11读取一个位 
       //返回值:1/0 
       unsigned 
       char 
       DHT11_Read_Bit
       (
       void
       ) 
       { 
         
       //数据为“0”格式:50us的低电平 + 26-28us的高电平 
       //数据为“1”格式:50us的低电平 + 70us的高电平 
       unsigned 
       char retry
       =
       0
       ; 
       while
       (DHT11_DQ_IN 
       && retry
       <
       100
       )
       //若为高电平说明上一位数据传输还未结束,等待变为低电平 
       { 
         retry
       ++
       ; 
       delay_us
       (
       1
       )
       ; 
       } retry
       =
       0
       ; 
       while
       (
       !DHT11_DQ_IN 
       && retry
       <
       100
       )
       //若为低电平,说明还未开始传输数据,等待变高电平 
       { 
         retry
       ++
       ; 
       delay_us
       (
       1
       )
       ; 
       } 
       delay_us
       (
       40
       )
       ;
       //等待40us 0为 50us低电平 26--28us高电平 1为 50us低电平 70us高电平 
       if
       (DHT11_DQ_IN
       ) 
       return 
       1
       ; 
       else 
       return 
       0
       ; 
       } 
       //从DHT11读取一个字节 
       //返回值:读到的数据 
       unsigned 
       char 
       DHT11_Read_Byte
       (
       void
       ) 
       { 
         
       unsigned 
       char i
       ,dat
       ; dat
       =
       0
       ; 
       for
       (i
       =
       0
       ;i
       <
       8
       ;i
       ++
       ) 
       { 
         dat
       <<=
       1
       ; dat
       |=
       DHT11_Read_Bit
       (
       )
       ; 
       } 
       return dat
       ; 
       } 
       //从DHT11读取一次数据 
       //temp:温度值(范围:0~50°) 
       //humi:湿度值(范围:20%~90%) 
       //返回值:0,正常;1,读取失败 
       unsigned 
       char 
       DHT11_Read_Data
       (
       unsigned 
       char 
       *temp
       ,
       unsigned 
       char 
       *humi
       ) 
       { 
         
       unsigned 
       char buf
       [
       5
       ]
       ; 
       unsigned 
       char i
       ; 
       DHT11_Rst
       (
       )
       ; 
       if
       (
       DHT11_Check
       (
       )
       ==
       0
       ) 
       //读取40位数据 
       { 
         
       for
       (i
       =
       0
       ;i
       <
       5
       ;i
       ++
       ) 
       { 
         buf
       [i
       ]
       =
       DHT11_Read_Byte
       (
       )
       ; 
       } 
       if
       (buf
       [
       0
       ]
       +buf
       [
       1
       ]
       +buf
       [
       2
       ]
       +buf
       [
       3
       ]
       ==buf
       [
       4
       ]
       )
       //湿度整数 湿度小数 温度整数 温度小数 校验和 
       { 
         
       *humi
       =buf
       [
       0
       ]
       ; 
       *temp
       =buf
       [
       2
       ]
       ; 
       } 
       } 
       else 
       return 
       1
       ; 
       return 
       0
       ; 
       } 
       //初始化DHT11的IO口 DQ 同时检测DHT11的存在 
       //返回1:不存在 
       //返回0:存在  
       unsigned 
       char 
       DHT11_Init
       (
       void
       ) 
       { 
         
       DHT11_IO_OUT
       (
       )
       ; DHT11_DQ_OUT
       =
       1
       ; 
       DHT11_Rst
       (
       )
       ; 
       return 
       DHT11_Check
       (
       )
       ; 
       } 
      

  读取温度时,直接在主函数中调用

#include "stm8s103f3p.h"
#include "delay.h"
#include "dht11.h"

//时钟配置 16Mhz
void CLK_Init(void)
{ 
       
	CLK_SWR=0xe1; 			 //HSI为主时钟源 16MHz CPU时钟频率
	CLK_CKDIVR=0x00;		//CPU时钟0分频,系统时钟0分频
}
//读取温度湿度数据
void read_tem_hum(void)
{ 
       
    unsigned char temperature[2]={ 
       0};
    unsigned char humidity[2]={ 
       0};
    DHT11_Read_Data(temperature,humidity);   
}
main()
{ 
       
    _asm("sim");			//关全部中断
    CLK_Init();
    delay_init(16);
    _asm("rim");			//开全部中断
  while (1)
    { 
       
        read_tem_hum();
    }
}

通过单片机的IO口输出高低电平来模拟单总线的时序,这样就可以将温度和湿度的数据读出来了。

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章