历史上的今天
今天是: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 驱动函数的编写;
将温湿度数据存储在数组中,利用相关显示函数将温湿度显示在屏幕上;
关于温湿度数据的读取,由于环境中温湿度变化不是很快,可以放在定时器里面读取。(本程序是放在了主函数中读取)
史海拾趣
|
随着负荷电流变化及环境温度变化,电力电缆会发生热伸缩,其中因线芯的热胀冷缩而产生非常大的热机械力,电缆线芯截面越大,所产生的热机械力就越大;同时线芯和金属护套还会因热胀冷缩的多次循环,而产生蠕变。热伸缩对电力电缆运行构成很大的威胁 ...… 查看全部问答> |
|
1. CCD尺寸,亦即微型摄像机靶面。原多为1/2英寸,现在1/3英寸的已普及化,1/4英寸和1/5英寸也已商品化。 2. CCD微型摄像机像素,是CCD的主要性能指标,它决定了显示图像的清晰程度,分辨率越高,图像细节的表现越好。CCD是由面阵感光元素组成, ...… 查看全部问答> |
|
有感于大家需要,共享下!内容包括电子设计时经常会碰到的电气图形符号,常用电子元器件型号命名法及主要技术参数,电阻器和电位器的型号命名方法,主要技术指标,电阻器的标志内容及方法,……… 查看全部问答> |
|
这款概念雨伞采用压缩空气作为遮雨部件。通过调整伞柄的控制按钮,您可以自如控制、调整雨伞的空气伞直径。这样一来,伞的部件便只剩下一支伞柄,而您也不用再为雨天撑伞进入室内,弄湿地板而发愁了! … 查看全部问答> |
|
大家好! 我想反DSP(EVMDM6437)采集到的YUV422图像通过网络发送到Windows xp上,结果出现了图像扭曲。 发送代码如下: timeout.tv_sec = 0; timeout.tv_usec = 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类型 请问我该怎么做? … 查看全部问答> |
|
英雄出少年 facebook CEO仅30岁坐拥315亿美元净资产 [摘要]扎克伯克正式成为全球第三个以10亿美元为单位净资产超出自己年龄的富豪。 BI中文站 7月25日报道本周早些时候,Facebook发布了2014财年第二季度财报。无论从哪方面看,都是一个完美的表现。在推动股价飙升的同时,公司CEO马克·扎克伯克(Ma ...… 查看全部问答> |




