STM32-DHT11(温湿度传感器)之学习笔记

一、模块分析:
原理图和引脚连接图:
STM32-DHT11(温湿度传感器)之学习笔记_第1张图片
由图可知DHT11(温湿度模块)是单总线的连接,数据的输入输出由一根线完成,DQ网络标号对应的引脚是PG9就是GPIO外设接口G组的第九个引脚。

二、DHT11时序图:

STM32-DHT11(温湿度传感器)之学习笔记_第2张图片

STM32-DHT11(温湿度传感器)之学习笔记_第3张图片
由上图可以判断当主机开始信号发送之后手袋DHT11响应信号并开始接受数据时,我们可以通过判断高电平的维持时间来获取当前接受的数据位是0/1这样就可以把数据保存下来。判断的依据是开始接受数据前延时超过26-28us,当延时过后检测到的还是高电平(高电平持续70us为数据1)那就证明该数据位为‘1’。因为每一个比特位传输完成之后会有50us的延迟所以当比特位为0时前面已经延时超过高电平时间所以比特位为0时,检测到的是低电平,由此来保存温湿度数据。

三、部分关键代码:
#include “dht11.h”
//单数据总线接口 —>PG9
void DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//1:第一步永远是打开时钟,查看固件库
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOG, ENABLE );

//对结构体成员进行赋值(输出 推挽   上拉  50MHZ)
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//输出模式
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

//2:对GPIOG进行初始化
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_Init( GPIOG ,&GPIO_InitStructure);

}

/*=2-配置GPIO口的输入模式函数=========*/
static void DHT11_Mode_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

//浮空输入
GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;   
GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_NOPULL;   //浮空输入 
GPIO_Init(GPIOG,&GPIO_InitStruct);

}

/*=2-配置GPIO口的输出模式函数=========*/
static void DHT11_Mode_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

//上拉推挽输出
GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;   
GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_UP;
GPIO_Init(GPIOG,&GPIO_InitStruct);

}

/3-配置8位接收数据函数,根据DHT11数据传输时序图编写=/
//数据是高位先出
static uint8_t Read_Byte(void)
{
uint8_t i,temp=0;

for(i=0;i<8;i++)
{
    //数据准备输出  每个数据都有50US的低电平,然后判断后面高电平是时长来决定是1还是0
    //0:高电平时长26~28us
    //1:高电平时长70us   
    /*每一个bit都是以50us的低电平开始,等电平置高,则跳出循环*/
    while( DQ_IN() == 0 );

    /*‘0’表示的置高时间过短,可直接判断‘1’表示的时间,但滞留时间不宜过长,以防跳出下一位的开始时间*/
    delay_us(40);
    
    if( DQ_IN() == 1 )//如果还是高电平,那就是数据1
    {
        /*等待跳出‘1’置高表示的时间*///等待剩余的高电平时间结束
        while( DQ_IN() == 1);
        /*把第(7-i)位置 '1'*/
        temp |= (uint8_t)(0x01<<(7-i));  
    }
    else
    {
        /*把第(7-i)位置 '0'*/
        temp &= (uint8_t)~(0x01<<(7-i));
    }
}
return temp;

}

/*
*功 能:获取温湿度值
*参 数:保存温度读数据的结构体指针
返回值:成功返回1 失败返回0
*
/
/
4-根据总时序图编写接收数据函数=
/
uint32_t DHT11_GET_TEMP_HUM(DHT11_Data_TypeDef * DHT11_Data)
{
uint16_t count = 0;

DHT11_Mode_OUT();//输出模式
DQ_OUT(0);       /*将主机拉低*/
delay_ms(20);/*配置主机拉低时间,至少拉低18ms*/
DQ_OUT(1);/*将主机拉高*/   
delay_us(30);

DHT11_Mode_IN();//输入模式    
if( DQ_IN() == 0) 
{    
    //printf("开始获取数据\r\n");
    //因为在空闲状态下,管教是高电平,所以这个时候如果是低电平,则模块有响应
    //等待拉高  时长80us
    while(DQ_IN() == 0)//等待80us结束
    {
        count++;
        if(count > 1000)
               return 0;
        delay_us(1);//每1us检测一次是否拉高
    }  
    //printf("80us low\r\n");
    count = 0;
    
    //等待拉高  时长80us
    while( DQ_IN()== 1)//等待80us结束
    {
        count++;
        if(count > 1000)
               return 0;
        delay_us(1);//每1us检测一次是否拉高
    }
   // printf("80us hight\r\n");
    
    // 获取5个字节数据 
    //分析40位数据,8Bit湿度整数   +8Bit湿度小数   +8Bit温度整数    +8Bit温度小数
    DHT11_Data->humi_int  = Read_Byte();
    DHT11_Data->humi_deci = Read_Byte();
    DHT11_Data->temp_int  = Read_Byte();
    DHT11_Data->temp_deci = Read_Byte();
    DHT11_Data->check_sum = Read_Byte();
   // printf("get data success\r\n");
    
/*读取结束,将主机设为输出模式*/
 DHT11_Mode_OUT();//输出模式
 DQ_OUT(1);/*将主机拉高,方便下次读取数据*/
    
if(DHT11_Data->check_sum == (DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci))                   
{    
    printf("校验和正常\r\n");
    return 1;
}
else
{
     printf("校验和失败\r\n");
     return 0;
}

}
else
return 0;

}

你可能感兴趣的:(嵌入式)