蓝桥杯嵌入式教程:使用扩展板DHT11实现温湿度检测(更新)

        没想到蓝桥杯官方资料更新到四梯官网了,今天才下到今年的国赛资源包

目录

一. 原理

1.初始化

2.DHT11_Check

3.数据采集

 二. 代码编写

1. dht11.c文件

2. dht.h文件

3. main.c 文件

三. 注意事项

结语


一. 原理

        从代码入手,按代码运行顺序来解释一下

1.初始化

        设置引脚为输出模式,并且拉高电平,高电平表示为总线空闲

2.DHT11_Check

        当DHT11接收到单片机的开始信号(拉低电平)后,等待单片机开始信号结束,然后发送80us低电平响应信号。
        单片机拉高电平表示开始信号结束,单片机需延时等待20-40us后,

        切换为输入模式。等待单片机发的高电平转成DHT11的80us低电平信号,再等待低电平结束,返回0,表示可以开始采集数据。

3.数据采集

        首先要等待上一步的高电平结束,然后低电平能才开始判断数据是0还是1。

数据0和1都可以分为两部分,前面一部分都是50us的低电平,只有后面的高电平时间不一样。为了更加方便写代码,可以利用数据0和1在这个地方的时间差,等过了28us,电平是低电平就是数据0,反之是1。所以会加一个延时。

数据0的时序图:

数据1的时序图:

 二. 代码编写

1. dht11.c文件

#include "dht11_hal.h"


dht11Data dht11;

//
static void usDelay(uint32_t us)
{
	uint16_t i = 0;
	while(us--){
		i = 30;
		while(i--);
	}
}

//
void outDQ(uint8_t i)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	
	GPIO_InitStructure.Pin = HDQ;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	if(!i) 
		HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_RESET);
	else 
		HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_SET);
}

//
void inDQ(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.Pin = HDQ;
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
	GPIO_InitStructure.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//
uint8_t DHT11_Check(void)
{
    uint8_t re = 0;
    inDQ();//设置为输入
	
    while (HAL_GPIO_ReadPin(GPIOA, HDQ) && re < 100) //DHT11会拉低40~80us
    {
        re++;
        usDelay(1);
    };
    if(re >= 100)return 1;
    else re = 0;
    while (!HAL_GPIO_ReadPin(GPIOA, HDQ) && re < 100) //DHT11拉低后会再次拉高40~80us
    {
        re++;
        usDelay(1);
    };
    if(re >= 100)return 1;
    return 0;
}
//
void dht11Init(void)
{
    __HAL_RCC_GPIOA_CLK_ENABLE();
	outDQ(1);		//空闲状态高电平
}

//
uint8_t recData(void)
{
	uint8_t i,temp=0;
	
	for(i=0; i<8; i++){
		while(HAL_GPIO_ReadPin(GPIOA,HDQ)&&n<100)
		{
			n++;
            usDelay(1);
		};	
		while(!HAL_GPIO_ReadPin(GPIOA,HDQ)&&m<100)
		{
			m++;
            usDelay(1);
		};			//等待低电平结束
		usDelay(40);	//卡时间
		if(HAL_GPIO_ReadPin(GPIOA,HDQ))
		{
			temp=(temp<<1)|1;
		}	
		else
		{
			temp=(temp<<1)|0;
		}
        n=0;
        m=0;
	}
	return temp;
}
void DHT11_Read_Data(float *temp, float *humi)
{
    uint8_t buf[5];
    uint8_t i;
		outDQ(0);
    HAL_Delay(20);	//拉低至少18ms
    HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_SET); 	//高电平
    usDelay(30);     	//主机拉高20~40us
		if(DHT11_Check() == 0)
    {
        for(i = 0; i < 5; i++)
        {
            buf[i] = recData();
        }
        if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
        {
            *humi = buf[0]+buf[1]/10.f;
            *temp = buf[2]+buf[3]/10.f;
        }
    }
  
}

2. dht.h文件

#ifndef __DHT11_HAL_H
#define __DHT11_HAL_H

#include "stm32g4xx_hal.h"

#define HDQ		GPIO_PIN_7

typedef struct {
	uint8_t humidity_high;
	uint8_t humidity_low;
	uint8_t temperature_high;
	uint8_t temperature_low;
}dht11Data;

void dht11Init(void);
//dht11Data* dht11Read(void);
void DHT11_Read_Data(float *temp, float *humi);

#endif

3. main.c 文件

        需要的可以参考这一篇:蓝桥杯嵌入式——扩展板DHT11_☆时光の星阵☆的博客-CSDN博客

        记得改头文件名、DHT11初始化函数名

三. 注意事项

(1)PA7-HDQ

结语

        不得不说我是怎么一步步改的。

        首先就是参照我之前改好的文件,添加了读取函数,发现不行,读取必须要改引脚模式为输入模式。

        后来又发现必须要写DHT11_Check,先判断能不能采集,就是到了DHT11发数据的时间没。不过还是不行,一般是时序问题,把之前的时延搬过来,不行。

        怀疑读取函数有问题,再搬过来,果然是的。

        最后稍微研究了一下读函数的问题,便解决了。

还是问题定位更加折磨啊!

物联沃分享整理
物联沃-IOTWORD物联网 » 蓝桥杯嵌入式教程:使用扩展板DHT11实现温湿度检测(更新)

发表评论