您现在的位置是:首页 >技术杂谈 >玩转传感器----理解时序和数据采集(DHT11)网站首页技术杂谈

玩转传感器----理解时序和数据采集(DHT11)

憨猪在度假 2023-07-13 20:00:02
简介玩转传感器----理解时序和数据采集(DHT11)

该文章以DHT11模块进行分析

目录

1.模块复位(时序图)

2.DHT11的应答信号

3.读取1bit数值(比较高电平的时间是否大于40us)

4.读取一个字节

5.把读取的字节放入单片机

6. 寄存器设置IO口方向


1.模块复位(时序图)

 void DHT11_Rst(void)       
{                 
    DHT11_IO_OUT();     //设置IO为输出
    DHT11_DQ_OUT=0;     //IO口置为低电平
    delay_ms(20);        //至少18ms
    DHT11_DQ_OUT=1;     //IO口置为高电平
    delay_us(30);        
}

2.DHT11的应答信号

u8 DHT11_Check(void)        
{   
    u8 retry=0;
    DHT11_IO_IN();//SET INPUT     
    while (DHT11_DQ_IN&&retry<100)
    {
        retry++;
        delay_us(1);
    };     
    if(retry>=100)return 1;
    else retry=0;
    while (!DHT11_DQ_IN&&retry<100)
    {
        retry++;
        delay_us(1);
    };
    if(retry>=100)return 1;        
    return 0;
}

这个地方时一个难点,巧妙读取io口电平的持续时间是否为80us,首先设置IO状态为输入,读取io电平,当io口为低电平时,DHT11_DQ_IN&&retry<100为true,执行retry++,延时1us;当跳变到高电平则DHT11_DQ_IN&&retry<100为false,若retry>100就提前结束。

3.读取1bit数值(比较高电平的时间是否大于40us)

 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);
    if(DHT11_DQ_IN)return 1;
    else return 0;           
}

 如果经过40us后,电平认为高则是1,反之为0。

4.读取一个字节

u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
    for (i=0;i<8;i++) 
    {
           dat<<=1; 
        dat|=DHT11_Read_Bit();//按位异或,与0异或=本身
    }                            
    return dat;
}

5.把读取的字节放入单片机

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++)
        {
            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;        

6. 寄存器设置IO口方向


#define DHT11_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DHT11_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}                                         
#define    DHT11_DQ_OUT PGout(11) 
#define    DHT11_DQ_IN  PGin(11)  

  |= 常用于位操作,目的是把值放入指定位置

&=0的目的是把该位置的位全部清0

操作高八位CR寄存器 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。