【STM32】STM32F407 + DHT11
【摘要】 stm32f407驱动DHT11,将温湿度显示在1.44寸液晶屏上。
Author:AXYZdong 自动化专业 工科男
有一点思考,有一点想法,有一点理性!
定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!
- 芯片类型:STM32F407VET6
- 开发环境:keil5 MDK
一、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
# @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
# @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
# @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 驱动函数的编写;
- 将温湿度数据存储在数组中,利用相关显示函数将温湿度显示在屏幕上;
- 关于温湿度数据的读取,由于环境中温湿度变化不是很快,可以放在定时器里面读取。(本程序是放在了主函数中读取)
本次的分享就到这里
好书不厌百回读,熟读自知其中意。将学习成为习惯,用知识改变命运,用博客见证成长,用行动证明努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏”
一键三连哦!
听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满呦!^ _ ^
**码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了👉关注👈我哦!
如果以上内容有任何错误或者不准确的地方,欢迎在下面👇留个言。或者你有更好的想法,欢迎一起交流学习~~~
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)