基于stm32单片机的DHT11温湿度模块使用

目录

一、DHT11模块介绍

目录

一、DHT11模块介绍

1、DHT11功能

2、DHT11数据传输

二、使用方法

1、时序介绍

2、数据包发送

3、代码实现


一、DHT11模块介绍

1、DHT11功能

对于温湿度模块来说,DHT11算是很经典的了,使用起来比较简单,但相对的功能上也没有那么强大。DHT11的湿度测量精度范围为20-90%RH(相对湿度),温度测量精度范围为0-50°C。但需要注意的是,DHT11的精度可能会受到环境因素的影响,如温度变化、湿度变化、气流等。因此,在使用DHT11进行测量时,应该尽量选择稳定的环境条件,以提高测量的准确度。

 

 DTH11有三个引脚的,也有四个引脚的,通常4个引脚的NC那个引脚也用不到,所以3个引脚的就够我们使用了。使用时把GND接地,VDD电源电压接高电平就行了,DATA则连上具体要用的单片机的GPIO口的引脚上。

2、DHT11数据传输

DHT11模块使用单线制数字信号串行通信。该通信协议称为DHT协议。在该协议中,DHT11模块只需要一根数据线就可以和主控设备进行通信。主控设备发送起始信号,DHT11响应并发送数据。每个数据包由40位二进制数据组成,其中包括16位湿度数据、16位温度数据和8位校验和。发送时序和接收时序都是非常重要的因素,对数据的准确性有很大影响。

二、使用方法

1、时序介绍

首先主机发送开始信号,即:拉低数据线,保持至少18ms时间t1,然后拉高数据线至少20~40us时间t2,然后读取DHT11的响应,正常的话,DHT11会拉低数据线,保持40~50us时间t3,作为响应信号,然后DHT11拉高数据线,保持40~50us时间t4后,开始输出数据。(如下图所示)

输出数据0,1的时序图如下:

DHT11会先拉低数据线12~14us时间,然后拉高数据线26~28us时间表示输出'0';在接着会重复的拉低数据线发送下一个bit,同样先拉低数据线至少12~14us时间,然后再拉高数据线至少116~118us的时间表示发送‘1’

2、数据包发送

通常发送40bit数据(5字节数据)来传送所检测到的温湿度数据。

数据格式:40bit数据=8位湿度整数+8位湿度小数+8位温度整数+8位温度小数+8位校验位;

例子:接收40位bit数据如下:

0000  0010      0000  0010          0000  0001    0000  0010          0000  0111

                湿度数据                                    温度数据                        校验和

 湿度高8位 + 湿度低8位 + 温度高8位 + 温度低8位  = 校验和

例如:0000 0001+0000 0010+0011 0001+0000 0010=0011 0110

二进制湿度数据0000  0010  0000 0010==>转化为十进制:514,除于10即为湿度值;

湿度=51.4%RH

二进制温度数据0000  0001  0000 0010==>转化为十进制:258,除于10即为湿度值;

温度=25.8℃

当温度低于0℃时温度数据的低八位最高位置1

例如:-34.1℃表示为 0010 0010 1000 0001

3、代码实现

 DHT11.c:

#include "stm32f10x.h"
#include "DHT11.h"

void DHT11_IO_IN(void)//温湿度模块端口输入初始化
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//端口复用

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void DHT11_IO_OUT(void)//温湿度模块端口输出初始化
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

//复位DHT11
void DHT11_Rst(void)
{
    DHT11_IO_OUT();                      //SET OUTPUT
    GPIO_ResetBits(GPIOB,GPIO_Pin_9)
    DelayXms(20);                        //拉低至少18ms
    GPIO_SetBits(GPIOB,GPIO_Pin_9);      
    DelayUs(30);                         //主机拉高20~40us
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)
{
    u8 retry = 0; //定义临时变量
    DHT11_IO_IN();//SET INPUT
    while ((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) == 1) && retry < 100) //DHT11会拉低40~80us
    {
        retry++;
        DelayUs(1);
    };
    if(retry >= 100)return 1;
    else retry = 0;
    while ((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) == 0) && retry < 100) //DHT11拉低后会再次拉高40~80us
    {
        retry++;
        DelayUs(1);
    };
    if(retry >= 100)return 1;
    return 0;
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void)
{
    u8 retry = 0;
    while((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) == 1) && retry < 100) //等待变为低电平
    {
        retry++;
        DelayUs(1);
    }
    retry = 0;
    while((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) == 0) && retry < 100) //等待变高电平
    {
        retry++;
        DelayUs(1);
    }
    DelayUs(40);//等待40us
    if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) == 1)
        return 1;
    else
        return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)
{
    u8 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,读取失败
u8 DHT11_Read_Data(u8 *temp, u8 *humi)
{
    u8 buf[5];
    u8 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 return 1;
    return 0;
}
//初始化DHT11的IO口  同时检测DHT11的存在
//返回1:不存在
//返回0:存在
void DHT11_Init(void)
{
    DHT11_Rst();  //复位DHT11
    DHT11_Check();//等待DHT11的回应
}

 main.c:

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "bmp.h"//汉字库
#include "DHT11.h"
#include "usart.h"	 

int main(void)
{

	u8 wd=0;      
  u8 sd=0;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  Delay_Init();
  uart_init(115200);
  
	DHT11_Init();
	
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示
  OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
	while(1)
	{
		
		DHT11_Read_Data(&wd,&sd);//读取温湿度值    

			
		printf("当前环境温度: %d ℃\r\n",wd);      //串口打印温湿度
		printf("当前环境湿度: %d %%\r\n",sd);
		
		
		OLED_ShowChinese(0,0,0,16,1); //温 x,y
		OLED_ShowChinese(18,0,1,16,1);//度
		OLED_ShowNum(50,0,wd,2,16,1);     //显示温度值
		OLED_ShowString(36,0,":",16,1);
		
		OLED_ShowChinese(0,16,2,16,1);//湿
		OLED_ShowChinese(18,16,1,16,1);//度	
		OLED_ShowNum(50,16,sd,2,16,1);    //显示湿度值
		OLED_ShowString(36,16,":",16,1);  
		OLED_ShowString(68,16,"%",16,1);   //
		delay_ms(1000);

		OLED_Refresh();

	}
}

  • 28
    点赞
  • 230
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值