wujian100学习笔记(2)驱动DHT11获取环境温湿度

DHT11

DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC测温元件,并与一个高性能 8 位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。 DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。

DHT11 的技术参数如下:

工作电压范围:3.3V -5.5V
工作电流 :平均 0.5mA
输出:单总线数字信号
测量范围:湿度 20~90%RH,温度 0~50℃
精度 :湿度±5%,温度±2℃

分辨率 :湿度 1%,温度 1℃

DHT11有效总线包含三条,VCC GND DAT,看起来与DS18B20类似,但是简单很多,不需要设置命令,只需要读取数据包就可以了,

每次读取数据一共读取40个BIT也就是五个字节,高位在前MSB

五个字节分别是:

8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据 +8bit校验和

如果前四个字节相加等于最后一个字节便说明数值正确,否则错误;

DHT11时序图

wujian100学习笔记(2)驱动DHT11获取环境温湿度_第1张图片
首先主机发送开始信号,即:(最开始状态依然是高电平)拉低数据线,保持** t1(至少 18ms)**时间,然后拉高数据线 t2(20~40us)时间,(此时需要转换输入输出模式)然后读取 DHT11 的响应,正常的话, DHT11 会拉低数据线,保持 t3 (40~50us)时间,作为响应信号,然后 DHT11 拉高数据线,保持 t4(40~50us)时间后,开始输出数据

也就是说,每次需要复位,检查响应,才能开始读数据,数据的格式如下
wujian100学习笔记(2)驱动DHT11获取环境温湿度_第2张图片
wujian100学习笔记(2)驱动DHT11获取环境温湿度_第3张图片
由此我们可以看到,每个数据都是有一个12-14us的低电平,是0还是1需要我们监测之后的高电平时间长度,基本上我们可以认为高电平持续时间大于35us的那一位便是1,否则为0;
(注意不能等待这个电平超过40us)因为一次0的时间就是40us,等待太长会可能丢掉下一个数据的起始位(这里我们可以用等待电平(为1或0)延时计数的模式来判定时间,当电平为0,等待它为1,每等待一次计数1us,最后看高电平持续时间)

wujian100驱动程序

dht11.h

#ifndef __DHT11_H
#define __DHT11_H
#include "stdio.h"
#include "soc.h"
#include "drv_gpio.h"
#include "stdlib.h"
#include "oled.h"

typedef uint8_t u8;

/* 设置IO口方向 */
#define DHT11_IO_IN()  		csi_gpio_pin_config(data,GPIO_MODE_PULLNONE,GPIO_DIRECTION_INPUT)
#define DHT11_IO_OUT()  	csi_gpio_pin_config(data,GPIO_MODE_PUSH_PULL,GPIO_DIRECTION_OUTPUT)
/* 设置IO口输出电平 */
#define DHT11_DQ_OUT_1()  	csi_gpio_pin_write(data,1)
#define DHT11_DQ_OUT_0()  	csi_gpio_pin_write(data,0)
/* 读取IO口输入电平 */
#define DHT11_DQ_IN       	csi_gpio_pin_read(data)    

/* 设置IO口对应的handle */
gpio_pin_handle_t data;

void Dht11Rst(void);//ReSet DHT11
u8 Dht11Check(void);//判断DHT11存在否
u8 Dht11ReadBit(void);//读一位值
u8 Dht11ReadByte(void);//读一个字节
u8 Dht11ReadData(u8 *temp,u8 *humi);//读5个字节,因为DHT11一次传输5个字节
int32_t PIN_INIT(int32_t idx);//显示温湿度
void Dht11Show(void);

#endif 

dht11.c

#include "dht11.h"

/**
  \brief       rst dht11
  \param[in]   NULL
  \return      NULL
*/
void Dht11Rst(void)	   
{                 
    DHT11_IO_OUT(); 				//SET OUTPUT
    DHT11_DQ_OUT_0(); 				//拉低DQ
    mdelay(25);    					//拉低至少18ms
    DHT11_DQ_OUT_1(); 				//DQ=1 
    udelay(35);     				//主机拉高20~40us
}

/**
  \brief       wait for dht11 to respond
  \param[in]   NULL
  \return      1.existence 0.no existence
*/
u8 Dht11Check(void) 	   
{   
    u8 retry=0;
    DHT11_IO_IN();					//改为输入,等待应答	 
    while (DHT11_DQ_IN&&retry<100)	//DHT11会拉低40~80us
    {
        retry++;
        udelay(1);
    } 
    if(retry>=100)return 1;
    else retry=0;
    while (!DHT11_DQ_IN&&retry<100)	//DHT11拉低后会再次拉高40~80us
    {
        retry++;
        udelay(1);
    }
    if(retry>=100)return 1;	    
    return 0;
}

/**
  \brief       read one bit 
  \param[in]   NULL
  \return      1 or 0
*/
u8 Dht11ReadBit(void) 			 
{
    u8 retry=0;
    while(DHT11_DQ_IN&&retry<100)	//等待变为低电平
    {
        retry++;
        udelay(1);
    }
    retry=0;
    while(!DHT11_DQ_IN&&retry<100)	//等待变高电平
    {
        retry++;
        udelay(1);
    }
    udelay(40);						//等待40us
    if(DHT11_DQ_IN)return 1;
    else return 0;		   
}

/**
  \brief       read one byte from dht11
  \param[in]   NULL
  \return      one byte
*/
u8 Dht11ReadByte(void)    
{        
    u8 i,dat;
    dat=0;
    for (i=0;i<8;i++) 
    {
        dat<<=1; 
        dat|=Dht11ReadBit();
    }						    
    return dat;
}

/**
  \brief       read data from dht11
  \param[in]   NULL
  \return      0.success 1.failed
*/
u8 Dht11ReadData(u8 *temp,u8 *humi)    
{        
    u8 buf[5];
    u8 i;
    Dht11Rst();
    if(Dht11Check()==0)
    {
        for(i=0;i<5;i++)			//读取40位数据
        {
            buf[i]=Dht11ReadByte();
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
        {
            *humi=buf[0];
            *temp=buf[2];
        }
    }else return 1;
    return 0;	    
}

/**
  \brief       gpio Initialize
  \param[in]   NULL
  \return      0.success -1.failed
*/
int32_t PIN_INIT(int32_t idx) 
{
	data = csi_gpio_pin_initialize(idx,NULL);
	
	if(data < 0) {
		printf("error\n");
		return -1;
	}
	
	csi_gpio_pin_config(data,GPIO_MODE_PUSH_PULL,GPIO_DIRECTION_OUTPUT);
	
	//csi_gpio_pin_write(data,1);
	//Dht11Rst();
	//return Dht11Check();
	return 0;
}

void Dht11Show(void)
{
	u8 temp,humi;
	if(!Dht11ReadData(&temp,&humi))
	{
		printf("温度: %d ℃ 湿度 %d %%\r\n",temp,humi);
		OLED_ShowNum(40,0,temp,3,16);
		OLED_ShowNum(40,3,humi,3,16);
	}
}

main.c

#include 
#include "oled.h"
#include "pin_name.h"
#include "pin.h"
#include "dht11.h"
int main()
{
	LCD_PIN_INIT(PA1,PA2,PA3,PA4,PA5);    			 //oled驱动引脚初始化
	PIN_INIT(PA8);                                   //dht11传输引脚初始化
	OLED_Init();			                         //初始化OLED  
	OLED_Clear() ;
	OLED_ShowString(0,0,"temp:");
	OLED_ShowString(0,3,"humi:");
	OLED_ShowString(70,0,"C");
	OLED_ShowString(70,3,"%");
	
	while(1)
	{
		Dht11Show();
		mdelay(5000);							     //5s进行一次采集环境温湿度
	}
}

测试结果:

串口输出:

wujian100学习笔记(2)驱动DHT11获取环境温湿度_第4张图片

OLED输出

wujian100学习笔记(2)驱动DHT11获取环境温湿度_第5张图片

我也是正在学习wujian100,希望可以结识到志同道合的小伙伴一起学习,因为这个平台毕竟是中国首个开源芯片平台,也存在着问题,还是很值得学习的。可以在评论区留下你的QQ,我们一起讨论,我们下期再见啦!

你可能感兴趣的:(笔记)