STM32简单读取DHT11温湿度数据

本文是关于对DHT11传感器进行数据的获取和处理

一,模块图片如下:

一般是4根线

从左到右分别为:

VDD:供电引脚3.3~5.5V DC

Data:穿行数据,单总线

NC:空脚

GND:接地,电源负极

二,总体说明:

简化版的单总线通信,有一根数据线,完成系统中的数据交换,控制,所以设计引脚模式的切换,这个后文会有提到,一次输出的数据有40位分别为湿度高低8位 温度高低8位 ,还有校验位

三,具体流程

步骤1

先进行一系列的准备,因为DHT11是单总线,所以要封装两个函数,反别设置引脚位是输出还是输入

static void DHT11_Mode_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOD,&GPIO_InitStruct);
}
static void DHT11_Mode_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOD,&GPIO_InitStruct);
}

可以理解为主机和从机,松手和放手 的关系

在初始化引脚后,就要奖DHT11的Data引脚拉高至于高电平,并且对于DHT11来说Data是输入

void DHT11_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOD,&GPIO_InitStruct);
    DHT11_High;
}

步骤2:

unsigned char Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)//这个地方和后面的步骤4拼接到一起
{

 DHT11_Mode_OUT();
 DHT11_Low;
 SysTick_delay_ms(20);//拉低不得低于18ms

  DHT11_High;    //按照时序再拉高

 SysTick_delay_us(30);//延时等待20~40us
 DHT11_Mode_IN();

步骤3:

这是对于读取到的数据进行一个判断

static uint8_t Read_Byte(void)
{
    uint8_t i,temp=0;
    for(i=0;i<8;i++)
    {
        while(Read_Data==0);//’0‘的格式是54us的低电平和23-27us的高电平

//1的格式是54us的低电平和68~74us的高电平,因为两者前面都是54us的低电平,所以等待低电平结束,再延时40us(这是一个中间值)再来判断是高电平还是低电平
        SysTick_delay_us(40);
        if(Read_Data==1){
            while(Read_Data==1);
            temp|=(uint8_t)(0x01<<(7-i));
        }
        else{
            temp&=(uint8_t)~(0x01<<(7-i));
        }
    }
    return temp;
}

步骤4:

 

主机将控制权给从机,也就是此时的引脚为输入模式,开始判断接收到的数据是不是低电平

if(Read_Data==0)
    {
        while(Read_Data==0);//大概54us
        while(Read_Data==1);//大概23-27us
        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();
        if(DHT11_Data->check_sum==(DHT11_Data->temp_deci+DHT11_Data->temp_int+DHT11_Data->humi_deci+DHT11_Data->humi_int))//这里用的是结构体存储,也可以用指针,我觉得结构体好看
        {
            return 1;
        }
        else{
            return 0;
        }
    }
    else{
        return 0;
    }

}

后面是头文件和宏定义记得:

#include "stm32f10x.h"                  // Device header
#define DHT11_High  GPIO_SetBits(GPIOD, GPIO_Pin_6)
#define DHT11_Low   GPIO_ResetBits(GPIOD, GPIO_Pin_6)
#define Read_Data   GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_6)
typedef struct
{
    uint8_t  humi_int;       
    uint8_t  humi_deci;        
    uint8_t  temp_int;       
    uint8_t  temp_deci;       
    uint8_t  check_sum;    
                         
}DHT11_Data_TypeDef;

最后是主函数部分:用的江协 的OLED屏幕代码

#include "stm32f10x.h"                  // Device header
#include  <USART.H>
#include <stdio.h>
#include <DHT11.H>
#include <OLED.H>
//uint8_t RXDate=0;
//uint8_t RX_Flag=0;
DHT11_Data_TypeDef DHT11_Data;
int main(void){
    OLED_Init();
    DHT11_GPIO_Config();
    OLED_ShowString(1, 1, "temp:");
    OLED_ShowString(2, 1, "humidity:");
    while(1)
    {
        if(Read_DHT11(&DHT11_Data) == 1)
        {
            OLED_ShowNum(2, 10, DHT11_Data.humi_int, 2);
            OLED_ShowString(2, 12, ".");
            OLED_ShowNum(2, 13, DHT11_Data.humi_deci, 2);
            
            OLED_ShowNum(1, 6, DHT11_Data.temp_int, 2);
            OLED_ShowString(1, 8, ".");
            OLED_ShowNum(1, 9, DHT11_Data.temp_deci, 1);
            
        }
    }
}

 

作者:怪盗坤洋

物联沃分享整理
物联沃-IOTWORD物联网 » STM32简单读取DHT11温湿度数据

发表评论