其他分享
首页 > 其他分享> > DTH11温湿度传感器使用(stm32)

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

作者:互联网

可以参考这个博客:
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