stm32f407与dht11通信,读取温湿度数据

1、背景介绍

stm32单片机要通过dht11模块,获取温湿度数据,改模块支持单总线通信,使用一根数据线,按照模块厂商规定通信时序,即可获取是温湿度数据,我们打算2s 采集一次温湿度数据,然后通过串口输出到上位机

2、具体步骤如下

  • 1、初始化GPIO口映射到DHT11的数据引脚
  • 2、设置引脚的工作模式(输入浮空:用于读取dht11发送过来的数据 | 开漏输出:用于输出0/1电平信号)
  • 3、发送启动信号,DHT11检测到启动信号后,发送一个应答信号,然后就开始传输40bit的数据、
  • 4、按照数据的高低电平时序,开始读取,
    • byte1-2:表示湿度高8位 + 低8位
    • byte3-4:表示温度高8位 + 低8位
    • byte5:表示byte1 + … + byte4 校验和 (这里的校验和只存储低8bit)

通讯时序图:

在这里插入图片描述

数据位时序图

在这里插入图片描述

3、代码

#include "TEMP.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"
u8 buffer[5] = {0,0,0,0,0};
// 设置IO为输出模式
void DHT11_IO_OUT(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;

 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
 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(GPIOG,&GPIO_InitStructure);
}

// 设置IO为输入模式
void DHT11_IO_IN(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;

 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//浮空输入
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出50MHz
 GPIO_Init(GPIOG,&GPIO_InitStructure);
}


// 复位DHT11
void DHT11_Reset(void){
  DHT11_IO_OUT();
  DHT11_DQ_OUT = 0; 	//拉低DQ
  delay_ms(20);
  DHT11_DQ_OUT = 1;
  delay_us(40);

}

void DHT11_Mode_Init(void){
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟;
}

// 初始化DHT11的io  DQ、 同时检测dht11的存在
u8 DHT11_Start_CollectData (void){
	
  u8 result = 0;	
  // 主机发送检测信号给dht11
  DHT11_Reset();
 
  // 等待dht11 响应MCU的呼叫
  result = DHT11_Response_CheckWait();
  return result;
}

//等待DHT11的回应
// 返回1:未检测到DHT11存在
// 返回0:检测到DHT11
u8 DHT11_Response_CheckWait(void){

	   u8 retry = 0;
	  // 主机设置为输入模式,准备接收dht11的响应
	  DHT11_IO_IN();
	  delay_us(20);
		
	 while(!DHT11_DQ_IN && retry < 100) {
		delay_us(1);
		retry++;
	 }
	 retry=0;
	 delay_us(30);
	 
	 if(retry >= 100) return 1;
	 else retry = 0;
	 
	 while(DHT11_DQ_IN && retry < 100) { 
		 // 跳出这里,说明现在dht11 开始响应数据给mcu
		delay_us(1);
		 retry++;
	 }
	 if(retry >= 100) return 1;
	 // 开始读取dht11 发送给mcu 的40bit数据
	 return 0;

}


// 读取所有温湿度数据(温度2byte + 湿度2byte + 1byte校验和)
u8 DHT11_ReadData(){
	u8 i;
	u32 sum = 0;
	// 发送采集信号
	if(DHT11_Start_CollectData() == 1){
		return 0;
	}
	// 连续读取5个字节
	// byte1~2:湿度高8bit、低8bit
	// byte3~4:温度高8bit、低8bit
	// bity5:byte1 ~ byte4 校验和
	for(i = 0 ;i<5;i++){
		buffer[i] = DHT11_ReadByte();
	}
	sum = (u8)(buffer[0] + buffer[1] + buffer[2] + buffer[3]);
	if(sum == buffer[4]){
		return 1;
	}else {
		return 0;
	}
}

// 读取1byte dht11 发过给MCU的数据
u8 DHT11_ReadByte(void){
	u8 temp;
	u8 i;
	u8 readByteData;
	u8 retry;
	for(i = 0 ;i < 8; i++){
	   while(!DHT11_DQ_IN && retry < 100){
		delay_us(1);
		retry++;
	   }
	   retry = 0;
	   // 此时dht11数据位变高,下面是判断高低电平的核心
	   delay_us(30);
	   temp = 0;
	   if(DHT11_DQ_IN == 1){
			temp = 1;
		    while(DHT11_DQ_IN && retry < 100) {
				delay_us(1);
				retry++;
			}
			retry = 0;
	   } else {
			temp = 0;
	   }
	   
	   readByteData<<=1;
	   readByteData |= temp;
	}
	return readByteData;
}


头文件代码:

#ifndef __TEMP_H
#define __TEMP_H

#include "sys.h"

#define	DHT11_DQ_OUT PGout(9) //数据端口	PG9 用去驱动IO口输出高低电平
#define	DHT11_DQ_IN  PGin(9)  //数据端口	PG9 用于读取io的高低电平


// 设置数据IO口的工作模式为:输入/输出
void DHT11_IO_OUT(void);
void DHT11_IO_IN(void);

u8 DHT11_ReadData(void);
u8 DHT11_ReadByte(void);
u8 DHT11_Response_CheckWait(void);
void DHT11_Reset(void);
void DHT11_Mode_Init(void);
u8 DHT11_Start_CollectData(void);
#endif


应用层代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "temp.h"
extern u8 buffer[5];
int main(void)
{ 
	u8 t=0;			    
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	
	LED_Init();					//初始化LED 
 	DHT11_Mode_Init(); 	
   

	while(1)
	{	    	    
			   
	 	delay_ms(10);
		t++;
		if(t==200)
		{
			if(DHT11_ReadData() == 1){
				printf("read temperature & humidity success !\r\n");
				printf("湿度:%d ,温度:%d ℃\r\n",buffer[0],buffer[2]);
			}
					
			LED0=!LED0;
		}
	}
}

4、实验结果:

上位机串口工具输出如下
在这里插入图片描述

小结

1、由于设计的问题,每次采集数据的时候,模块内部存储的是上次采集的数据,故而,我们需要采集2次,才能确保获取到最新准确的数据
2、每次采集前,需要检测一下模块是否能正常响应,然后再开始采集数据,否则程序直接返回、、
3、

参考资料

DHT11产品手册
参考B站视频 : DHT11温湿度读取

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值