传感器学习——DHT11

DHT11简介

DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。
传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机
DHT11 的技术参数如下:
 工作电压范围: 3.3V-5.5V
 工作电流 :平均 0.5mA
 输出:单总线数字信号
 测量范围: 湿度 20~90%RH,温度 0~50℃
 精度 :湿度±5%,温度±2℃
 分辨率 :湿度 1%,温度 1℃

DHT11数据格式

首先主机发送开始信号,即:拉低数据线,保持 t1(至少 18ms)时间,然后拉高数据线 t2(20~40us)时间,然后读取 DHT11 的响应,正常的话, DHT11 会拉低数据线,保持 t3(40~50us)时间,作为响应信号,然后 DHT11 拉高数据线,保持 t4(40~50us)时间后,开始输出数据。

在这里插入图片描述
湿度= byte4 . byte3=45.0 (%RH)
温度= byte2 . byte1=28.0 ( ℃)
校验= byte4+ byte3+ byte2+ byte1=73(=湿度+温度)

DHT11发送顺序为从低位到高位,Byte是先湿度后温度,先整数后小数,最后校验和。

DHT11通信方式

首先主机发送开始信号,即:拉低数据线,保持 t1(至少 18ms)时间,然后拉高数据线 t2(20~40us)时间,然后读取 DHT11 的响应,正常的话, DHT11 会拉低数据线,保持 t3(40~50us)时间,作为响应信号,然后 DHT11 拉高数据线,保持 t4(40~50us)时间后,开始输出数据。
在这里插入图片描述
DHT11发送的数据不是传统的“高电平就是1,低电平就是0”,而是在每发送一个bit前,拉低电平 12 ~14us。数据是体现在拉高电平时间的长短,拉高电平26 ~28us,就为0,拉高电平116 ~118us就为1。
在这里插入图片描述在这里插入图片描述

程序源码

dht11.c

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

//复位 DHT11 
void DHT11_Rst(void)    
{                 
 DHT11_IO_OUT();   //SET OUTPUT 
  DHT11_DQ_OUT=0;  //拉低 DQ 
  delay_ms(20);    //拉低至少 18ms 
  DHT11_DQ_OUT=1;  //DQ=1 
 delay_us(30);      //主机拉高 20~40us 
}
//等待 DHT11 的回应 
//返回 1:未检测到 DHT11 的存在 
//返回 0:存在 
u8 DHT11_Check(void)     
{   
 u8 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 
  u8 DHT11_Read_Bit(void)     
{
  u8 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
 if(DHT11_DQ_IN)return 1;
 else return 0;     
}
//从 DHT11 读取一个字节 
//返回值:读到的数据 
u8 DHT11_Read_Byte(void)     
{        
    u8 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,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi)     
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
  u8 buf[5];
 u8 i;
 DHT11_Rst();
 if(DHT11_Check()==0)
 {
  for(i=0;i<5;i++)//读取 40 位数据 
  {
   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:存在      
 u8 DHT11_Init(void) 
{
 GPIO_InitTypeDef  GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能 GPIOG 时钟 
 //GPIOF9,F10 初始化设置   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;   GPIO_InitStructure.GPIO_Mode =GPIO_Mode_OUT;//普通输出模式 
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 
GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 DHT11_Rst();
return DHT11_Check(); 
}

dht11.h

#ifndef __DHT11_H
#define __DHT11_H 
#include "sys.h"   


//IO方向设置
#define DHT11_IO_IN()  {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=0<<9*2;} //PG9输入模式
#define DHT11_IO_OUT() {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=1<<9*2;}  //PG9输出模式
////IO操作函数
#define DHT11_DQ_OUT PGout(9) //数据端口 PG9 
#define DHT11_DQ_IN  PGin(9)  //数据端口 PG9 
u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度
u8 DHT11_Read_Byte(void);//读出一个字节
u8 DHT11_Read_Bit(void);//读出一个位
u8 DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11    
#endif
发布了6 篇原创文章 · 获赞 11 · 访问量 138

猜你喜欢

转载自blog.csdn.net/weixin_46156693/article/details/104460599