【STM32】STM32F407 + DHT11

Author:AXYZdong 自动化专业 工科男
有一点思考,有一点想法,有一点理性!
定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!
CSDN@AXYZdong,CSDN首发,AXYZdong原创
唯一博客更新的地址为: 👉 AXYZdong的博客 👈
B站主页为: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
# @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 驱动函数的编写;
  • 将温湿度数据存储在数组中,利用相关显示函数将温湿度显示在屏幕上;
  • 关于温湿度数据的读取,由于环境中温湿度变化不是很快,可以放在定时器里面读取。(本程序是放在了主函数中读取)

  本次的分享就到这里


11

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “收藏” “关注” 一键三连哦!
更多精彩内容请前往 AXYZdong的博客


如果以上内容有任何错误或者不准确的地方,欢迎在下面 👇 留个言。或者你有更好的想法,欢迎一起交流学习~~~

  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
STM32F407单片机读写OneWire_DHT11温湿度传感器(串口屏显示)软件工程源码,可以做为你的学习设计参考。 int main(void) { /* 复位所有外设,初始化Flash接口和系统滴答定时器 */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化串口并配置串口中断优先级 */ MX_DEBUG_USART_Init(); HMI_USARTx_Init(); DHT11_Init(); /* 无限循环 */ while (1) { /*调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息*/ if(DHT11_Read_TempAndHumidity(&DHT11_Data)==SUCCESS) { HMI_value_setting("page1.gross.val",DHT11_Data.humidity*10); HMI_value_setting("page1.net.val",DHT11_Data.temperature*10); printf("读取DHT11成功!-->湿度为%.1f %RH ,温度为 %.1f℃ \n",DHT11_Data.humidity,DHT11_Data.temperature); } else { printf("读取DHT11信息失败\n"); } HAL_Delay(1000); } } /** * 函数功能: 向串口屏发送数据 * 输入参数: 无 * 返 回 值: 无 * 说 明: 无 */ void HMI_value_setting(const char *val_str,uint32_t value) { uint8_t tmp_str[30]={0}; uint8_t i; sprintf((char *)tmp_str,"%s=%d",val_str,value); for(i=0;iDR=tmp_str[i]; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); HMI_USARTx->DR=0xFF; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } /** * 函数功能: 向串口屏发送浮点数据 * 输入参数: 无 * 返 回 值: 无 * 说 明: 无 */ void HMI_string_setting(const char *val_str,int32_t value) { uint8_t tmp_str[50]={0}; uint8_t i; float temp=(float)value; sprintf((char *)tmp_str,"%s=\"%.1f\"",val_str,temp/100); for(i=0;iDR=tmp_str[i]; while(__HAL_UART_GET_FLAG(&husartx_HMI, UART_FLAG_TXE) == RESET); } HMI_USARTx->DR=0xFF;
DHT11是一种温湿度传感器,可以通过单片机进行读取并处理数据。以下是一个基于STM32F407微控制器的DHT11驱动代码示例: ```c #include "stm32f4xx.h" #define DHT11_PORT GPIOB #define DHT11_PIN GPIO_Pin_0 void Delay_us(uint32_t n) { uint32_t i; for(i=0; i<n; i++); } void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStruct.GPIO_Pin = DHT11_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(DHT11_PORT, &GPIO_InitStruct); GPIO_SetBits(DHT11_PORT, DHT11_PIN); Delay_us(500); } void DHT11_Start(void) { GPIO_ResetBits(DHT11_PORT, DHT11_PIN); Delay_us(18000); GPIO_SetBits(DHT11_PORT, DHT11_PIN); Delay_us(40); } uint8_t DHT11_Read_Bit(void) { uint8_t retry=0; while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)==RESET) { retry++; if(retry>100) return 0; Delay_us(1); } retry=0; while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)==SET) { retry++; if(retry>100) return 0; Delay_us(1); } if(retry<8) return 0; else return 1; } uint8_t DHT11_Read_Byte(void) { uint8_t i, data=0; for(i=0; i<8; i++) { data<<=1; data|=DHT11_Read_Bit(); } return data; } uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi) { uint8_t check_sum; DHT11_Start(); if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)==RESET) { while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)==RESET); while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)==SET); *humi=DHT11_Read_Byte(); *temp=DHT11_Read_Byte(); check_sum=DHT11_Read_Byte(); if(check_sum==(*humi+*temp)) return 1; } return 0; } int main(void) { uint8_t temp, humi; DHT11_Init(); while(1) { if(DHT11_Read_Data(&temp, &humi)==1) { printf("Temperature: %d Celsius, Humidity: %d%%\n", temp, humi); } Delay_us(1000000); } } ``` 在这个示例中,我们初始化了DHT11引脚并定义了一些基本的函数,如延迟函数,DHT11启动函数,读取单个位和单个字节的函数,以及读取温湿度数据的函数。在主函数中,我们通过DHT11传感器读取温湿度数据,并在串口上输出。请注意,此示例代码可能需要根据您的具体硬件环境进行适当的修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AXYZdong

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值