历史上的今天
返回首页

历史上的今天

今天是:2024年12月09日(星期一)

正在发生

2021年12月09日 | 【STM32】STM32F407 + DHT11

2021-12-09 来源:eefocus

一、DHT11简介

DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~95%RH, 温度-20~+60℃。


——来自百度百科


测量范围:湿度 5~95%RH, 温度 -20~+60℃

测量精度:湿度 ±5%RH, 温度 ±2℃

供电电压:3.3~5.5V DC

输 出:单总线数字信号

分辨率:湿度1%RH, 温度0.1℃

关于单总线协议可以查看这篇文章:【STM32】stm32f407 + DS18B20 碰出不一样的火花


二、编程思路

温湿度传感器 DHT11 和 温度传感器 DS18B20 均采用 单总线协议,因此两者的编程思路很相似,不过 DHT11 增加了湿度的测量。


说明:在移植代码时,注意引脚的变换,选择合适的引脚,本程序中使用 PB5 作为单总线通讯的引脚。如要修改引脚,只需修改头文件中引脚的相关宏定义。


DHT11.h

// =============================================

# @Time    : 2021-08-08

# @Author  : AXYZdong

# @CSDN    : https://axyzdong.blog.csdn.net/

# @FileName: DHT11.h

# @Software: keil5 MDK

// =============================================

#ifndef __DTH11_H

#define __DTH11_H

#include "stm32f4xx.h"

 

/************************** DS18B20 连接引脚定义********************************/

#define    RCC_DHT11                          RCC_AHB1Periph_GPIOB

#define    DHT11_DQ_GPIO_PORT                 GPIOB

#define    DHT11_DQ_GPIO_PIN                  GPIO_Pin_5


/************************** DS18B20 函数宏定义********************************/

#define    DHT11_DQ_L             GPIO_ResetBits ( DHT11_DQ_GPIO_PORT, DHT11_DQ_GPIO_PIN ) 

#define    DHT11_DQ_H             GPIO_SetBits ( DHT11_DQ_GPIO_PORT, DHT11_DQ_GPIO_PIN ) 



/************************** DS18B20 函数声明 ********************************/


void DHT11_Init(void);

u8 DHT11_Read_Data(u8 *temp,u8 *humi);


#endif /* __DS18B20_H */


DHT11.c

// =============================================

# @Time    : 2021-08-08

# @Author  : AXYZdong

# @CSDN    : https://blog.csdn.net/qq_43328313

# @FileName: DHT11.c

# @Software: keil5 MDK

// =============================================

#include "stm32f4xx.h"

#include "dth11.h"

#include "delay.h"


/*******************************************************************************

 * 函数名:DHT11_GPIO_Config

 * 描述  :配置DHT11用到的I/O口

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

void DHT11_GPIO_Config(void)

  GPIO_InitTypeDef GPIO_InitStructure; 

  RCC_AHB1PeriphClockCmd(RCC_DHT11, ENABLE);       /*开启DS18B20对应的GPIO的外设时钟*/ 

  GPIO_InitStructure.GPIO_Pin = DHT11_DQ_GPIO_PIN; /*选择要控制的DS18B20引脚*/ 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;      /*设置引脚模式输出模式*/       

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     /*设置引脚的输出类型为推挽输出*/

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  /*设置引脚速率为50MHz */ 

  GPIO_Init(DHT11_DQ_GPIO_PORT, &GPIO_InitStructure); /*调用库函数,初始化相应GPIO*/

}

/*******************************************************************************

 * 函数名:DHT11_Mode_Out

 * 描述  :使DHT11-DATA引脚变为输出模式

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

static void DHT11_Mode_Out(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

/*选择要控制的DHT11_DQ_GPIO_PORT引脚*/    

  GPIO_InitStructure.GPIO_Pin = DHT11_DQ_GPIO_PIN;

/*设置引脚模式输出模式*/

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   

  /*设置引脚的输出类型为推挽输出*/     

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

/*设置引脚速率为50MHz */   

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

/*调用库函数,初始化DHT11_DQ_GPIO_PORT*/

  GPIO_Init(DHT11_DQ_GPIO_PORT, &GPIO_InitStructure);

}

/*******************************************************************************

 * 函数名:DHT11_Mode_IN

 * 描述  :使DHT11-DATA引脚变为输入模式

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

static void DHT11_Mode_IN(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


  /*选择要控制的DS18B20_DQ_GPIO_PORT引脚*/

  GPIO_InitStructure.GPIO_Pin = DHT11_DQ_GPIO_PIN;


   /*设置引脚模式为浮空输入模式*/ 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;


  /*调用库函数,初始化DS18B20_DQ_GPIO_PORT*/

  GPIO_Init(DHT11_DQ_GPIO_PORT, &GPIO_InitStructure);

}

/*******************************************************************************

 * 函数名:DHT11_Reset

 * 描述  :初始化DHT11

 * 输入  :无

 * 输出  :无

 * 返回值:初始化成功为0,不成功为1

 *******************************************************************************/

void DHT11_Reset() 

{      

  DHT11_Mode_Out(); //SET OUTPUT

    DHT11_DQ_L; //DQ=0

    delay_ms(20);    //拉低至少18ms

    DHT11_DQ_H; //DQ=1 

    delay_us(30);     //主机拉高20~40us

}

u8 DHT11_Check(void)    

{   

u8 retry=0;//定义临时变量

DHT11_Mode_IN();//SET INPUT 

while ((GPIO_ReadInputDataBit(DHT11_DQ_GPIO_PORT,DHT11_DQ_GPIO_PIN)==1)&&retry<100)//DHT11会拉低40~80us

{

   retry++;

   delay_us(1);

}; 

if(retry>=100)return 1;

else retry=0;

  while ((GPIO_ReadInputDataBit(DHT11_DQ_GPIO_PORT,DHT11_DQ_GPIO_PIN)==0)&&retry<100)//DHT11拉低后会再次拉高40~80us

{

   retry++;

   delay_us(1);

};

if(retry>=100)return 1;    

return 0;

}

//从DHT11读取一个位

//返回值:1/0

u8 DHT11_Read_Bit(void)  

{

u8 retry=0;

while((GPIO_ReadInputDataBit(DHT11_DQ_GPIO_PORT,DHT11_DQ_GPIO_PIN)==1)&&retry<100)//等待变为低电平

{

retry++;

delay_us(1);

}

retry=0;

while((GPIO_ReadInputDataBit(DHT11_DQ_GPIO_PORT,DHT11_DQ_GPIO_PIN)==0)&&retry<100)//等待变高电平

{

retry++;

delay_us(1);

}

delay_us(40);//等待40us

if(GPIO_ReadInputDataBit(DHT11_DQ_GPIO_PORT,DHT11_DQ_GPIO_PIN)==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_Reset();

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口 DQ 同时检测DHT11的存在

//返回1:不存在

//返回0:存在     

void DHT11_Init(void)

{     

DHT11_GPIO_Config();

DHT11_Reset();  //复位DHT11

DHT11_Check();//等待DHT11的回应

}


main.c

// =============================================

# @Time    : 2021-08-08

# @Author  : AXYZdong

# @CSDN    : https://axyzdong.blog.csdn.net/

# @FileName: main.c

# @Software: keil5 MDK

// =============================================

#include "stm32f4xx.h"

#include "delay.h"

#include "QDTFT_demo.h"

#include "Lcd_Driver.h"

#include "GUI.h"

#include "dth11.h"

#include "usart.h"

#include "bsp_key.h"

#include "time.h"


u8 wd=0, sd=0;

u8 tab_wd[5],tab_sd[5];

char set_date=28;

char Set_date[5];


int main(void)

{

    SystemInit(); //System init.

    delay_init(168);//Delay init.

Lcd_Init();

Lcd_Clear(WHITE);

    DHT11_Init();

Debug_USART_Config();

QDTFT_Test_Demo(); //See the test details in QDTFT_Demo.c

  while(1)

  { 

        DHT11_Read_Data(&wd,&sd);

       

tab_wd[0] = wd/10 + 0x30;

tab_wd[1] = wd%10 + 0x30;

tab_wd[2] = 'C';


tab_sd[0] = sd/10 + 0x30;

tab_sd[1] = sd%10 + 0x30;

tab_sd[2] = '%';

Set_date[0] = set_date/10 + 0x30;

Set_date[1] = set_date%10 + 0x30;

Set_date[2] = 'C';

Gui_DrawFont_GBK16(15,30,RED,WHITE,(u8 *)tab_wd);

        Gui_DrawFont_GBK16(15,70,RED,WHITE,(u8 *)tab_sd);    

Gui_DrawFont_GBK16(87,90,RED,WHITE,(u8 *)Set_date);

  }

}


现象:TFT屏幕上显示当前的温度值和湿度值。


三、总结

DHT11 驱动函数的编写;

将温湿度数据存储在数组中,利用相关显示函数将温湿度显示在屏幕上;

关于温湿度数据的读取,由于环境中温湿度变化不是很快,可以放在定时器里面读取。(本程序是放在了主函数中读取)

推荐阅读

史海拾趣

Crystal Semiconductor Corp公司的发展小趣事

随着市场竞争的加剧,Crystal Semiconductor Corp意识到只有不断创新才能在行业中立足。于是,公司加大了对研发的投入,引进了一批高端人才。经过数年的努力,公司成功开发出了一种新型的半导体制程工艺,大幅提高了晶体管的性能和可靠性。这一创新不仅为公司带来了丰厚的利润,也为整个半导体行业树立了新的标杆。

Cadeka公司的发展小趣事

随着电子行业的快速发展,Cadeka公司意识到单一市场的局限性。为了拓展业务,公司开始实施全球化战略布局。首先,Cadeka在欧洲和亚洲设立了研发中心,与当地高校和研究机构合作,共同开发新技术。同时,公司还在全球范围内建立了生产基地和销售网络,以便更好地服务全球客户。

Dongguan Jingyue Electronics Co Ltd公司的发展小趣事

随着公司业务的不断扩大,Dongguan Jingyue Electronics Co Ltd面临着越来越复杂的供应链管理问题。为了降低成本、提高效率,公司决定对供应链进行优化。通过引入先进的供应链管理软件和系统,加强与供应商和物流公司的合作,公司成功实现了供应链的数字化和智能化管理,提高了整体运营效率。

CLARE公司的发展小趣事

随着技术的不断进步和市场的日益成熟,CLARE公司开始致力于产品的创新和升级。公司研发团队紧跟科技前沿,不断探索新技术、新材料和新工艺的应用,推出了一系列具有创新性和领先性的电子产品。这些产品不仅满足了客户的需求,还引领了市场的潮流,进一步提升了CLARE公司的品牌影响力和市场竞争力。

Cybernetic Micro Systems公司的发展小趣事

为了进一步拓展业务领域,CMS开始寻求跨界合作。他们与一家领先的汽车制造商达成战略合作,共同研发车载智能系统。CMS的芯片技术为车载系统提供了强大的计算能力和数据处理能力,使得车载系统更加智能化、便捷化。这一合作不仅为CMS带来了新的收入来源,也进一步提升了公司的品牌影响力。

FASTRAX公司的发展小趣事

随着公司业务的不断发展,FASTRAX开始积极拓展海外市场,并与多家国际知名企业建立了战略合作关系。通过与这些企业的合作,FASTRAX不仅获得了更多的市场份额,也学习到了先进的管理经验和技术知识。这些合作经验为FASTRAX的持续发展奠定了坚实的基础。

问答坊 | AI 解惑

电力电缆布线热伸缩及其对策浅谈

随着负荷电流变化及环境温度变化,电力电缆会发生热伸缩,其中因线芯的热胀冷缩而产生非常大的热机械力,电缆线芯截面越大,所产生的热机械力就越大;同时线芯和金属护套还会因热胀冷缩的多次循环,而产生蠕变。热伸缩对电力电缆运行构成很大的威胁 ...…

查看全部问答>

微型摄像机监控的主要技术指标

1. CCD尺寸,亦即微型摄像机靶面。原多为1/2英寸,现在1/3英寸的已普及化,1/4英寸和1/5英寸也已商品化。 2. CCD微型摄像机像素,是CCD的主要性能指标,它决定了显示图像的清晰程度,分辨率越高,图像细节的表现越好。CCD是由面阵感光元素组成, ...…

查看全部问答>

工程师必备——常用电子元器件资料(焊接工艺)

有感于大家需要,共享下!内容包括电子设计时经常会碰到的电气图形符号,常用电子元器件型号命名法及主要技术参数,电阻器和电位器的型号命名方法,主要技术指标,电阻器的标志内容及方法,………

查看全部问答>

【有奖竞猜】什么元件

别猜二极管, 第一猜中者奖芯币50枚 …

查看全部问答>

空气伞 无形的保护层

这款概念雨伞采用压缩空气作为遮雨部件。通过调整伞柄的控制按钮,您可以自如控制、调整雨伞的空气伞直径。这样一来,伞的部件便只剩下一支伞柄,而您也不用再为雨天撑伞进入室内,弄湿地板而发愁了! …

查看全部问答>

求助!WinSock 和 DSP数据传输问题

大家好!     我想反DSP(EVMDM6437)采集到的YUV422图像通过网络发送到Windows xp上,结果出现了图像扭曲。 发送代码如下:         timeout.tv_sec  = 0;     timeout.tv_usec = 0;   & ...…

查看全部问答>

WinCE4.2和EVC4.0安装问题!!!

各位大侠:     小弟我今天安装WinCE4.2版本,然后安装了EVC4.0,EVC SP2和STANDARD_SDK. 但是出现以下问题: 1 安装完WinCE4.2时,电脑的右下角标出现了以下提示:    Virtual PC/Windows CE/Emulator 会造成WINDOWS不稳定,WIN ...…

查看全部问答>

EVC下如何将一个CString类型转换成一个double类型?

CString str; str=L\"111.111\"; 现在我想把这个CString类型变量的字符串变成double类型 请问我该怎么做? …

查看全部问答>

线形光耦原理与电路设计

本帖最后由 paulhyde 于 2014-9-15 03:43 编辑 …

查看全部问答>

英雄出少年 facebook CEO仅30岁坐拥315亿美元净资产

[摘要]扎克伯克正式成为全球第三个以10亿美元为单位净资产超出自己年龄的富豪。 BI中文站 7月25日报道本周早些时候,Facebook发布了2014财年第二季度财报。无论从哪方面看,都是一个完美的表现。在推动股价飙升的同时,公司CEO马克·扎克伯克(Ma ...…

查看全部问答>