通过时序图编程操作DHT11读取温湿度

目录

一、DHT11模块

二、时序图分析

总的时序:

开始信号与响应信号:

读取数据:

停止信号:

三、程序部分


一、DHT11模块

 

        Dht11温湿度检测模块,模块引出引脚有VCC、GND和DATA,只有一根DATA线用于传输数据。数据格式内容手册中有介绍:

二、时序图分析

总的时序:

总的流程:

主机发送开始信号->主机读取响应信号->开始接收数据->主机发送停止信号。

空闲状态为高电平。

开始信号与响应信号:

        主机引脚配置输出模式,主机将信号线拉低至少18ms后拉高,随后主机引脚配置输入模式,此处可以等待60us后读取读取信号若为低电平,再等待80us后若读到高电平则认为成功读取到响应信号。

读取数据:

数据0和1的发送都是从低电平开始的,因此当读到低电平时该准备接收数据,0与1的表示由高电平的持续时间有关,0为26-28us,1为70us,因此当读到高电平时开始计时,若在28-70us后读到高电平则数据为1,否则为0。为确保准确取28-70us的中间部分值。

       40bit为5个字节,可一个字节一个字节数据接收,接收5次即可。

停止信号:

接收结束主机将信号线拉高为空闲状态即可。

串口打印数据:

三、程序部分

        在整个读取过程中需要来回改变数据引脚的输入输出模式,直接对寄存器操作即可;

          ​​​​​​​        

改变输入输出模式:

{GPIOE->MODER &= ~(3<<2*0);GPIOE->MODER |= (1<<2*0);}		//输出模式
{GPIOE->MODER &= ~(3<<2*0);GPIOE->MODER &= ~(3<<2*0);}	    //输入模式

 完整的程序:

dht11.h文件:

#ifndef _DHT11_H__
#define _DHT11_H__

#include "stm32f4xx.h" 
#include "sys.h"         //实现位带操作的头文件


#define DHT11_IO_GROUP_RCC 	RCC_AHB1Periph_GPIOE 	//使能的IO组
#define DHT11_IO_GROUP 			GPIOE				//IO组
#define DHT11_IO_PIN  			GPIO_Pin_3			//引脚

#define DHT11_DAT_OUT  (PEout(0))
#define DHT11_DAT_IN   (PEin(0))

#define DHT11_DAT_OUT_MODE()	{GPIOE->MODER &= ~(3<<2*0);GPIOE->MODER |= (1<<2*0);}		//输出模式
#define DHT11_DAT_IN_MODE() 	{GPIOE->MODER &= ~(3<<2*0);GPIOE->MODER &= ~(3<<2*0);}	//输入模式


extern char dht11_data[5];

void DHT11_Init(void);
char DHT11_Read_Data(void);


#endif

dht11.c文件:

#include "dht11.h" 
#include "delay.h" 
#include <stdio.h> 
#include <string.h> 

char dht11_data[5];  //温湿度缓存区


/***************************************************************************
* 函数名称:DHT11_Init
* 功    能:DHT11数据引脚初始化 
* 说		明:无
* 参		数:无
* 返		回:无
*	作		者:chengzhou
****************************************************************************/
void DHT11_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(DHT11_IO_GROUP_RCC, ENABLE);	//使能GPIO时钟
  //GPIO初始化设置
  GPIO_InitStructure.GPIO_Pin = DHT11_IO_PIN ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;			//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//50MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			//上拉
  GPIO_Init(DHT11_IO_GROUP, &GPIO_InitStructure);		//初始化GPIO
	
	GPIO_SetBits(DHT11_IO_GROUP,DHT11_IO_PIN );				//设置高
}
/***************************************************************************
* 函数名称:DHT11_Star
* 功    能:DHT11开始信号 
* 说		明:无
* 参		数:无
* 返		回:无
*	作		者:chengzhou
****************************************************************************/
static void DHT11_Star(void)
{
	DHT11_DAT_OUT_MODE(); //输出模式
	DHT11_DAT_OUT = 1;
//	delay_ms(10);
	DHT11_DAT_OUT = 0;
	delay_ms(20);				//拉低至少18ms
	DHT11_DAT_OUT = 1;  //主机拉高

}
/***************************************************************************
* 函数名称:DHT11_Ack
* 功    能:读取DHT11响应信号 
* 说		明:无
* 参		数:无
* 返		回:成功:1,失败:0
*	作		者:chengzhou
****************************************************************************/
static char DHT11_Ack(void)
{
	DHT11_DAT_IN_MODE();	//输入模式
	delay_us(60);					//加上需等待的20-40us
	if(DHT11_DAT_IN == 0)	//DHT开始发送响应信号,低电平
	{
		delay_us(80);
		if(DHT11_DAT_IN)	//再发高电平
			return 1;
	}
	return 0;
}
/***************************************************************************
* 函数名称:DHT11_Stop
* 功    能:DHT11停止信号 
* 说		明:无
* 参		数:无
* 返		回:无
*	作		者:chengzhou
****************************************************************************/
static void DHT11_Stop(void)
{
	DHT11_DAT_OUT_MODE(); //输出模式
	DHT11_DAT_OUT = 1;
}
/***************************************************************************
* 函数名称:DHT11_Read_One_Byte
* 功    能:DHT11读取一个字节数据 
* 说		明:无
* 参		数:无
* 返		回:读取到的数值
*	作		者:chengzhou
****************************************************************************/
static char DHT11_Read_One_Byte(void)
{
	char i,data = 0,time = 0;
	for(i=0;i<8;i++)
	{
		time =0;
		while(DHT11_DAT_IN ==1 && time <100)//等待上一个信号结束,等待100us
		{
			time++;
			delay_us(1);
		}
		time =0;
		while(DHT11_DAT_IN ==0 && time <100)//等待高电平到来(信号到来),等待100us
		{
			time++;
			delay_us(1);
		}	
		delay_us(35);			//延时大于28us小于70us
		
		data <<=1;				//先左移再读取
		if(DHT11_DAT_IN)	//读到1
			data +=1;
		
	}	
	return data;
}
/***************************************************************************
* 函数名称:DHT11_Read_Data
* 功    能:DHT11读取数据 
* 说		明:无
* 参		数:无
* 返		回:成功:1,失败:0
*	作		者:chengzhou
****************************************************************************/
char DHT11_Read_Data(void)
{
	char j,time = 0;
	memset(dht11_data,0,5);	//清空缓存区
	
	DHT11_Star();
	if(DHT11_Ack())	//正常读取到ack信号
	{
		DHT11_DAT_IN_MODE();	//引脚输入模式	
		while(DHT11_DAT_IN	&& time<100)	//等待响应信号结束,等待100us
		{
			time++;
			delay_us(1);
		}
		
		for(j=0;j<5;j++)		//5个字节40bit,读5次
		{
			dht11_data[j] = DHT11_Read_One_Byte();
		}
		
		DHT11_Stop();
		if(dht11_data[0] + dht11_data[1] + dht11_data[2] + dht11_data[3] == dht11_data[4])	//校验
			return 1;		//读取成功
		return 0;//读取失败
	}
	
	else
	{
		DHT11_Stop();
		return 0;//读取失败
	}
}

main.c文件中:

#include "stm32f4xx.h"                  // Device header
#include "sys.h"
#include "delay.h" 
#include "dht11.h" 
#include "usart.h"	


int main(void)
{
	float tem = 0.0,hum = 0.0;
	delay_init(168);
	uart_init(115200);
	DHT11_Init();
	
	printf("DHT11实验\r\n");

	for(;;)
	{
		delay_ms(500);
		delay_ms(500);
		delay_ms(500);
		delay_ms(500);
		if(DHT11_Read_Data())
		{
			printf("DHT11读取成功\r\n");
		}
		hum = dht11_data[0] + dht11_data[1]/256.0;
		tem = dht11_data[2] + dht11_data[3]/256.0;

		printf("tem:%.2f ℃\r\n",tem);
		printf("hum:%.2f %\r\n",hum);	
		printf("\r\n");		
	}
		
}

  • 2
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值