ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

DTH11温湿度传感器使用(stm32)

2021-06-08 16:06:07  阅读:394  来源: 互联网

标签:char DTH11 温湿度 void unsigned stm32 IO DQ DHT11


可以参考这个博客:
https://blog.csdn.net/qq_27508477/article/details/83661672
但是由于stm32f103很难得到1us的时钟,而且使用HAL库没有直接的寄存器操作,所以需要一定的修改,这里主要讲如何修改。

DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度20-90%RH, 温度0~50℃。
DHT11利用单总线协议,因此有严格的时序。
主机先要发送一个至少18ms的低电平,在这个过程中,DHT11内部完成AD转换等操作,当主机拉高后,有20-40us时间,这个时间用于主机做输入输出切换,当主机释放总线控制权(此时主机为输入状态,总线被上拉电阻拉高),DHT11尝试将总线拉低,成功拉低后就开始准备发送数据了,再拉高一次就开始传输数据了。
在这里插入图片描述
具体传输过程如下,其中数据0和数据1依靠高电平持续时长来判断。
一个bit数据发送完之后会把总线拉低,反过来说应该是拉低一段时间后开始采样。
在这里插入图片描述
数据0表示方法:
在这里插入图片描述
数据1表示方法:
在这里插入图片描述

使用stm32cubeMX新建工程

使用的是stm32f103c8,新建工程如下:
这是在一个系统中建立的过程,包括一个30us定时器中断,调试用的uart,以及几个io口。在DTH11的使用中,实际上不需要这些io口,所以这一步的关键在于读者自省摸索如何使用该工具。
stm32cubeMX可以可视化配置管脚,之后生成keil工程,用户只需要在该工程的指定位置添加自己的代码就行了。
生成代码可以参考此链接:
https://blog.csdn.net/qq_45467083/article/details/103525751在这里插入图片描述

修改HAL_Delay单位为10us

在这里插入图片描述

修改源代码

这里主要是重写以下几个宏定义

//这个是源代码中的,修改后不需要
#define DHT11_IO_IN()  {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;}	//PE9输入模式
#define DHT11_IO_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} 	//PE9输出模式 
//#define	DHT11_DQ_OUT PEout(9) //数据端口	PE9 
#define	DHT11_DQ_IN()  PEin(9)  //数据端口	PE9

此外还要将原来的1us级延时改为10us级延时。
修改后的代码如下:
dth11.h

#ifndef __DHT11_H
#define __DHT11_H 

#include "sys.h"

int DHT11_DQ_IN(void);
void DHT11_DQ_OUT(int state);
void DHT11_IO_OUT(void);
void DHT11_IO_IN(void);

unsigned char DHT11_Init(void);//初始化DHT11
unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi);//读取温湿度
unsigned char DHT11_Read_Byte(void);//读出一个字节
unsigned char DHT11_Read_Bit(void);//读出一个位
unsigned char DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11    
#endif

dth11.c

#include "dht11.h"

#define DTH11_GPIO GPIOB
#define DTH11_PIN GPIO_PIN_6
//IO方向设置
//#define DHT11_IO_IN()  {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;}	//PE9输入模式
//#define DHT11_IO_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} 	//PE9输出模式 

void DHT11_IO_IN(void)//设置GPIOB_6为输入
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
	
  GPIO_InitStruct.Pin = DTH11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(DTH11_GPIO, &GPIO_InitStruct);
	
}
void DHT11_IO_OUT(void)//设置GPIOB_6为输出
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
	
  GPIO_InitStruct.Pin = DTH11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DTH11_GPIO, &GPIO_InitStruct);
}

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
unsigned char DHT11_Init(void)
{
//	DHT11_IO_OUT();
//	for(int i=0;i<100;i++){
//		DHT11_DQ_OUT(i%2);HAL_Delay(10000);
//	}
//	DHT11_IO_IN();
//	for(int i=0;i<500;i++){
//		printf("%d ",DHT11_DQ_IN());HAL_Delay(10000);
//	}
	DHT11_IO_OUT();
	DHT11_Rst();
	return DHT11_Check();
}

IO操作函数											   
//#define	DHT11_DQ_OUT PEout(9) //数据端口	PE9 
void DHT11_DQ_OUT(int state)
{
	if(state == 1){
		HAL_GPIO_WritePin(DTH11_GPIO, DTH11_PIN, GPIO_PIN_SET);
	}else{
		HAL_GPIO_WritePin(DTH11_GPIO, DTH11_PIN, GPIO_PIN_RESET);
	}
	
}
//#define	DHT11_DQ_IN()  PEin(9)  //数据端口	PE9 
int DHT11_DQ_IN(void)//设置GPIOB_7输出
{
	return ((DTH11_GPIO->IDR & DTH11_PIN)!= (uint32_t)GPIO_PIN_RESET)?GPIO_PIN_SET:GPIO_PIN_RESET;
}

//复位DHT11
void DHT11_Rst(void)	    
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
	DHT11_DQ_OUT(0); 	//拉低DQ
	HAL_Delay(2000);    	//拉低至少18ms
	DHT11_DQ_OUT(1); 	//DQ=1 
	HAL_Delay(3);     	//主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
unsigned char DHT11_Check(void) 	   
{   
	unsigned char retry=0;
	DHT11_IO_IN();//SET INPUT	 
  while (DHT11_DQ_IN()&&retry<10)//DHT11会拉低40~80us
	{
		retry++;
		HAL_Delay(1);
	};
	if(retry>=10){
		printf("#1");
		return 1;
	}else retry=0;
    while (!DHT11_DQ_IN()&&retry<10)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		HAL_Delay(1);
	};
	if(retry>=10){
		printf("#2");
		return 1;
	}    
	return 0;
}
//从DHT11读取一个位
//返回值:1/0
unsigned char DHT11_Read_Bit(void) 			 
{
 	unsigned char retry=0;
	while(DHT11_DQ_IN()&&retry<10)//等待变为低电平
	{
		retry++;
		HAL_Delay(1);
	}
	retry=0;
	while(!DHT11_DQ_IN()&&retry<10)//等待变高电平
	{
		retry++;
		HAL_Delay(1);
	}
	HAL_Delay(4);//等待40us
	if(DHT11_DQ_IN())return 1;
	else return 0;		   
}
//从DHT11读取一个字节
//返回值:读到的数据
unsigned char DHT11_Read_Byte(void)    
{        
	uint8_t i,dat;
	dat=0;
	for (i=0;i<8;i++) 
	{
		dat<<=1; 
		dat|=DHT11_Read_Bit();
	}						    
	return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi)    
{        
 	uint8_t buf[5];
	uint8_t i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0];
			*temp=buf[2];
		}else{
			printf("wrong read: buf:%2d  buf:%2d\r\n",buf[0],buf[2]);
			return 2;
		}
	}else return 1;
	return 0;	    
}

测试代码:

	//初始化
	if(DHT11_Init()!=0){//初始化DHT11
		printf("dht11 init wrong!\n\r\n");
	}else{
		printf("dht11 init ok!\n\r\n");
	}
	
  while (1)
  {
    unsigned char temperature=0, humidity=0;
	if(DHT11_Read_Data(&temperature,&humidity)!=0){
		//读取温湿度值出错
	}
	HAL_Delay(150000);
    printf("temperature:%2d    humidity:%2d\r\n",temperature,humidity);
  }

标签:char,DTH11,温湿度,void,unsigned,stm32,IO,DQ,DHT11
来源: https://blog.51cto.com/u_15262460/2882982

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有