DHT11温湿度传感器数据采集教程(附STM32代码)

一、所需准备

硬件:DHT11模块(奥松电子)、DHT11资料手册、串口模块、STM32F103C8T6最小系统板、杜邦线

软件:Keil 5 、串口助手

DHT11资料手册-某盘链接

https://pan.baidu.com/s/1vC3wLzLvLqBAO0dkiWCYIw 提取码:pppp

二、引脚说明

模块工作流程可以简化为:①MCU唤醒DHT11 ,让DHT11开始工作。 ②DHT11传输温度和湿度数据MCU,MCU接收DHT11的数据。

  注:DATA线决定数据何时发送何时接收,用另一种表达,DATA线控制数据的收发

三、代码

1.宏定义

本文DATA连接的是PB3

/*我这里DATA连接的是PB3*/

#define  DHT11_DATA_H    GPIO_SetBits(GPIOB, GPIO_Pin_3)           //PB3输出高电平
#define  DHT11_DATA_L    GPIO_ResetBits(GPIOB,GPIO_Pin_3)          //PB3输出低电平
#define  DHT11_IN        GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_3)   //PB3输入

2.管脚配置/初始化

首先我们从资料手册可以得知设备通过漏极开路连至该数据线,且单总线通常要求外接了一个约5.1kΩ的上拉电阻,因此DATA线的空闲电平为高电平。

所以我们将与DATA线所连接的引脚配置为通用开漏输出。此时可能有人有疑问:配置成输出模式如何接收DHT11的数据?

这时我们就要用到GPIO口的一个特性:配置成输出模式的时候,输入功能正常使用。配置成输入模式的时候,输出功能无法使用。

产品手册中还写到上电后需要等待1秒以上同时保持高电平。

注:STM32F103C8T6想要使用PB3需要调整JTAG/SWD复用功能重映射,需要设置成关闭JTAG-DP,启用SW-DP。


void Dht11_Init(void)
{
	
	//1、打开时钟
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOB的时钟

    /*想要使用PB3需要调整JTAG/SWD复用功能重映射,关闭JTAG-DP,启用SW-DP*/

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开AFIO时钟
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭JTAG-DP,开启SW-DP
	
	//2、IO初始化,配置管脚
	
	GPIO_InitTypeDef GPIO_InitStruct={0};
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//配置为通用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;//配置管脚
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//IO速度为50Mhz
	GPIO_Init(GPIOB,&GPIO_InitStruct);

	delay_ms(1000);//DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令
	DHT11_DATA_H;//拉高,释放总线
}

3.起始信号

从产品手册,可知要先DATA线先拉低18ms以上再拉高

void Dht11_Start(void)
{
	
	DHT11_DATA_L;
	delay_ms(25);
	DHT11_DATA_H;
	
	
}

4.响应信号

由产品手册可知,DHT11接收到外部信号后会输出一个低电平,再输出一个高电平。

u8 Dht11_Ack(void)
{
	
	while(DHT11_IN); // 等待DHT11发送响应号

	
	while(!DHT11_IN);//等待80us低电平结束
	
	while(DHT11_IN);//等待80us高电平结束
  
	return  0;
}

5.接收数据

我们判断数据是 " 1 " 还是 " 0" 的方法就是区分高电平的时间,所以我们可以在延时35us后查看GPIO口电平状况,若还是高电平则是数据 " 1 ",反之则为数据" 0 "。

我们可以多种接收数据的方法,比如先接收32位数据再接收剩下8位数据,但为了取数据简便,我选择一次接收8位数据的方法,分5次接收

u8 Dht11_Rec(void)
{

	u8 data=0;
	for(u8 i= 0;i < 8;i++)
	{
		while(!DHT11_IN);//等待50us低电平结束
		delay_us(35); //延时35us查看是否是高电平
		data <<=1;
		if(DHT11_IN ==1) //判断数据是 1 还是 0
		{
		   data |=1;
		}
		while(DHT11_IN);//等待高电平结束,准备接收下一位数据
	}
	return data;
	
}

6.整合

由产品手册可知,依次出的是湿度整数、湿度小数、温度整数、温度小数、校验位。

为了方便我们设置一个数组来接收数据。

u8 Dht11_Integrate(float *temp,float *humi)
{
    u8 data[5]; //设置一个数组用来接收数据,也可以设置五个不同的变量用于接收
	Dht11_Start(); //发送起始信号
    Dht11_Ack(); //等待DHT11应答

	data[0] = Dht11_Rec();//湿度整数
	data[1] = Dht11_Rec();//湿度小数
	data[2] = Dht11_Rec();//温度整数
	data[3] = Dht11_Rec();//温度小数
	data[4] = Dht11_Rec();//校验位
     if( data[4] == data[0]+data[1]+data[2]+data[3] ) //校验数据是否正确
    {
	  *temp=data[2] + data[3] /10.0;  //温度数据
	  *hu=data[0] +data[1] /10.0 ; // 湿度数据
	
	  return 0;
    }
    return 1; //若不正确返回 1
}

最后我们可以使用串口助手或显示屏将得到的温湿度数据显示出来,串口部分代码和主函数部分代码就省略了。

注:上述代码只适用于测试零上温度。

效果图如下:

作者:芝士苦瓜汽水

物联沃分享整理
物联沃-IOTWORD物联网 » DHT11温湿度传感器数据采集教程(附STM32代码)

发表回复