[STM32]HAL库STM32CubeMX+DHT11温湿度传感器

本文详细介绍了如何使用STM32F103C8T6微控制器通过STM32CubeMX和KeilIDE与DHT11数字温湿度传感器进行单线通信,包括DHT11的工作原理、接口说明、通讯过程和程序编写,涉及微秒级延时函数、IO口配置、数据读取等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

所用的工具:

知识概括:

DHT11介绍:

DHT11性能说明:

接口说明

 电源引脚

串行接口  

工程创建

1、设置RCC

2、时钟设置

3、项目文件设置

4、设置IO口(DATA)

5、TIM时钟配置

6、USART配置

  程序编写:

         1、TIM3实现微秒(us)级延时函数:

2、IO口配置

3、DHT11检测起始信号(这里的DHT11_LOW,DHT11_HIGH 在下面的的第8点)

4、DHT11检测响应信号(这里的DHT11_IO_IN在下面的第8点)

5、DHT11读取一bit数据

6、DHT11读取一个Byte数据

7、DHT11读取湿度和温度的数据

8、IO口输出高、低电平以及读取IO口电平定义和需要添加的头文件

9、温度、湿度和数据缓存数组的声明,函数的声明

10、主循环,(DHT11数据的读取和串口发送)

效果展示

1、将程序下载到开发板

2、串口助手查看数据​编辑

总结 

附录(完整程序)


所用的工具:

1、芯片:STM32F103C8T6

2、软件:STM32CubeMX软件

3、IDE :   MDK_Keil软件

知识概括:

DHT11基本知识和原理

DHT11通讯方式

STM32CubeTIM和USART的配置

DHT11数据采集实现

DHT11介绍:

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传
感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高
的可靠性与卓越的长期稳定性。

DHT11性能说明:

接口说明

建议连接线短语20m时用5K的上拉电阻,大于20m时根据实际情况使用合适的上拉电阻

 电源引脚

        DHT11的供电电压为 3.3~5v。传感器上电后,要等待1s,以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100uf电容,用以去耦滤波。

串行接口  

DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程下:
           一次完整的数据传输为40bit,高位先出。
         数据格式: 8bit湿度整数数据+8bit湿度小数数据
                          +8bi温度整数数据+8bit温度小数数据
                          +8bit校验和
        数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。
        用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后 转换到低速模式。
*接下来就是重点中的重点了!!
DHT11的通讯过程:
        

        总线空闲状态为高电平,主机把总线拉低等待DHT11响应, 主机 把总线拉低必须 大于18毫秒 ,保证DHT11能检测到起始信号。当DHT11接收到主机的起始信号之后,会拉高总线并且等待。开始信号的结束后,将DATA切换成输入模式(这里的DATA指的是那个模块上的IO口切换成输入模式),随后总线为低电平,说明 DHT11 发出 80us低电平 的响应信号,发出响应信号之后 , DHT11 再次把总线 拉高80us ,准备开始发送数据, 数据是以一bit位的方式传输 当最后一bit数据传送完毕后 DHT11 拉低总线50us,随后总线由上拉电阻拉高进入空闲态。
下面这张图的延迟时长非常重要,需要在程序中用到

         总线空闲状态为高电平, 主机 把总线拉低等待DHT11响应,主机把总线拉低必 须 大于18毫秒 ,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后, 拉高总线 20us~40us ,等待开始信号结束后, DHT11 发出 80us低电平 的响应信号,发出响应信号之后 , DHT11 再次把总线 拉高80us 并且准备输出数据。
        下面这张是DHT11数据传输的时序图:
        数字0信号表示方法如图所示:
     数字1信号表示方法如图所示:

        

         总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态

工程创建

1、设置RCC

2、时钟设置

 3、项目文件设置

  • 1 设置项目名称
  • 2 设置存储路径
  • 3 选择所用IDE

1、 复制所用文件的.C和.H

2、每个功能生成独立的.C和.H文件

 4、设置IO口(DATA)

第二步的Moed设置GPIO_OUTPUT和GPIO_INPUT都可以,因为DHT11是单线双向的 ,所以在编写程序时我们需要改写的它IO模式。  

5、USART配置

第二步 Mode设置为异步通信 

  程序编写:

   首先来编写函数部分:

    1、微秒(us)级延时函数:

void delay_us(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
	{
		;
	}
}

该函数用了逻辑分析仪进行了比较,示图如下:

100us:

10us:

1us:

2、IO口配置

/**
  * @brief  DATA引脚(PA7)设置为输出模式
  * @param  无
  * @retval 无
  */
void DHT11_OUT(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct = {0};

	GPIO_InitStruct.Pin = GPIO_PIN_7;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
  * @brief  DATA引脚(PA7)设置为输入模式
  * @param  无
  * @retval	无 
  */
void DHT11_IN(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct = {0};

	GPIO_InitStruct.Pin  = GPIO_PIN_7;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

3、DHT11检测起始信号(这里的DHT11_LOW,DHT11_HIGH 在下面的的第8点

/**
  * @brief  DHT11检测起始信号
  * @param  无
  * @retval 无
  */
void DHT11_Strat(void)
{
	DHT11_OUT();   //PA7设置为输出模式
	DHT11_LOW;     //主机拉低总线
	HAL_Delay(20); //延迟必须大于18ms ; 
	DHT11_HIGH;    //主机拉高总线等待DHT11响应
	Delay_us(30);   
}

4、DHT11检测响应信号(这里的DHT11_IO_IN在下面的第8点

/**
  * @brief  DHT11发送响应信号
  * @param  无
  * @retval 返回值0/1  0:响应成功 1:响应失败
  */
uint8_t DHT11_Check(void)
{
	uint8_t retry = 0 ;
	DHT11_IN();
	//采用while循环的方式检测响应信号
	while(DHT11_IO_IN && retry <100) // DHT11会拉低 40us ~80us
	{
		retry++;
		Delay_us(1);//1us
	}
	if(retry>=100) //判断当DHT11延迟超过80us时return 1 , 说明响应失败
	{return  1;}
	else retry =  0 ;
		
	while(!DHT11_IO_IN && retry<100)// // DHT11拉低之后会拉高 40us ~80us
	{
		retry++;
		Delay_us(1);//1us
	}
		
	if(retry>=100)
	{return 1;}
	return 0 ;
}

5、DHT11读取一bit数据

/**
  * @brief  DHT11读取一位数据
  * @param  无
  * @retval 返回值0/1  1:读取成功 0:读取失败
  */
uint8_t DHT11_Read_Bit(void)
{
	uint8_t retry = 0 ;
	while(DHT11_IO_IN && retry <100)//同上采用while循环的方式去采集数据
	{
		retry++;
		Delay_us(1);
	}
	retry = 0 ;
	while(!DHT11_IO_IN && retry<100)
	{
		retry++;
		Delay_us(1);
	}

	Delay_us(40);              //结束信号,延时40us 
	if(DHT11_IO_IN) return 1;  //结束信号后,总线会被拉高 则返回1表示读取成功
	else 
	return 0 ;
}

6、DHT11读取一个Byte数据

/**
  * @brief  DHT11读取一个字节数据
  * @param  无
  * @retval 返回值:dat 将采集到的一个字节的数据返回
  */
uint8_t DHT11_Read_Byte(void)
{
	uint8_t i , dat ;
	dat = 0 ;
	for(i=0; i<8; i++)
	{
		dat <<= 1; //通过左移存储数据
		dat |= DHT11_Read_Bit();
	}
	return dat ; 
}

7、DHT11读取湿度和温度的数据

/**
  * @brief  DHT11读取数据
  * @param  temp:温度值 humi :湿度值
  * @retval 返回值0/1 0:读取数据成功 1:读取数据失败
  */
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi)
{
	uint8_t buf[5];        //储存五位数据
    uint8_t i;    
	DHT11_Strat();         //起始信号
	if(DHT11_Check() == 0) //响应信号
    {
		for(i=0; i<5; i++)
		{
			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 ;
}

以上就是需要用到的函数部分的编写,接下来是一些声明和定义:

8、IO口输出高、低电平以及读取IO口电平定义和需要添加的头文件

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DHT11_HIGH     HAL_GPIO_WritePin(GPIOA, DHT11_Pin,	GPIO_PIN_SET) //输出高电平
#define DHT11_LOW      HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)//输出低电平

#define DHT11_IO_IN      HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)//读取IO口电平

/* USER CODE END PD */
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include	"stdio.h"
#include  "string.h"

/* USER CODE END Includes */

9、温度、湿度和数据缓存数组的声明,函数的声明


  /* USER CODE BEGIN 1 */
     uint8_t temperature = 1;  //温度

	 uint8_t humidity = 1;     //湿度

	 uint8_t aTXbuf[32];       //串口发送缓存数组
     
     DHT11_Strat(void);

  /* USER CODE END 1 */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

void Delay_us(uint16_t delay);                //us级延时函数

//DHT11_DATA ,IO口设置为输出模式(这里的IO口指的是STM32CubeMX中配置的IO口)
void DHT11_OUT(void);	
												
void DHT11_IN(void);                          //DHT11_Data IO设置为输入模式
void DHT11_Strat(void);				          //主机发出起始信号
uint8_t DHT11_Check(void);                    //DHT11发送响应信号
uint8_t DHT11_Read_Bit(void);                 //读取DHT11一个BIT的数据
uint8_t DHT11_Read_Byte(void);                //读取DHT11一个Byte的数据
uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi);  //读取DHT11湿度和温度的数据

/* USER CODE BEGIN PFP */

10、主循环,(DHT11数据的读取和串口发送)

  while (1)
  {
	//接收DHT11的温度和湿度的值
	DHT11_Read_Data(&temperature , &humidity);  
    //将数据存放到aTXbuf这个数组当中去。 不了解"sprintf"用法的可以去查一下...       
	sprintf((char*)aTXbuf,"温度:%d℃,湿度: %d %%\r\n" ,temperature ,humidity);
    //将数据通过串口发送到主机上的串口助手
	HAL_UART_Transmit(&huart1, aTXbuf, strlen((const char*)aTXbuf), 200); 
    //延时500ms
	HAL_Delay(500);   

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

到这里DHT11的程序就编写完了 ,下面就来看看效果吧 

效果展示

1、将程序下载到开发板

 2、串口助手查看数据

总结 

通过本次DHT11温湿度传感器的学习,掌握了单线双向的数据通信方式DHT11和主机之间数据通讯过程,而且在此过程中要注意延时函数的把控精度,在编写程序中DHT11数据读取方式,数据传输方式和数据存储方式,以及微秒级延迟函数的编写,本设计参考正点原子探索者开发板教程STM32Cube高效开发指南(高级篇)

附录

后面是整理的DHT11的.C和.H文件 ,下述文件的跟上面不同(请分开使用)微秒级延时无需用定时器操作这样只会占用外设资源。  这个延时没有问题,数据不出来的原因1、引脚的编号是否需改   2、DQ口是否给了上拉电阻,如果硬件上拉了,软件可以不上拉。(打印方式还是使用上面的串口打印的方式)

#include "dht11.h"

void delay_us(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
	{
		;
	}
}

/**
  * @brief  DATA引脚(PA7)设置为输出模式
  * @param  无
  * @retval 无
  */
void DHT11_IO_OUT()
{
		GPIO_InitTypeDef  GPIO_InitStruct = {0};

		GPIO_InitStruct.Pin = DHT11_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
  * @brief  DATA引脚设置为输入模式
  * @param  无
  * @retval	无 
  */
void DHT11_IO_IN()
{
		GPIO_InitTypeDef  GPIO_InitStruct = {0};

		GPIO_InitStruct.Pin  = DHT11_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_LOW; 	//拉低DQ
    HAL_Delay(20);    	//拉低至少18ms
    DHT11_HIGH; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT	 
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ_IN&&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(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)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口 DQ 同时检测DHT11的存在
返回1:不存在
返回0:存在    	 
//u8 DHT11_Init(void)
//{
//	RCC->APB2ENR|=1<<8;    //使能PORTG口时钟 
//	GPIOG->CRH&=0XFFFF0FFF;//PORTG.11 推挽输出
//	GPIOG->CRH|=0X00003000;
//	GPIOG->ODR|=1<<11;      //输出1				    
//	DHT11_Rst();
//	return DHT11_Check();
//}
























DHT11.H 程序

#ifndef __DHT11_H
#define __DHT11_H 
#include "main.h"   

//IO方向设置
#define DHT11_HIGH     HAL_GPIO_WritePin(GPIOA, DHT11_Pin,	GPIO_PIN_SET)
#define DHT11_LOW      HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)
#define DHT11_DQ_IN    HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)
#define u8 uint8_t

u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度
u8 DHT11_Read_Byte(void);	//读出一个字节
u8 DHT11_Read_Bit(void);	//读出一个位
u8 DHT11_Check(void);		//检测是否存在DHT11
void DHT11_Rst(void);		//复位DHT11    
#endif


声明:该设计资料来源于立创社区,仅供网友学习参考,不可用于商业用途。 基于STM32 的 USB温湿度计概述: 该USB温湿度计基于STM32F070F6P6 设计完成。STM32F070F6P6 是ST公司新出品不久的一款 ARM Cortex-M0芯片,内置 32 Kbytes Flash,6K SRAM,12Bit ADC,运行主频48MHZ,支持USB 2.0 SLAVE通信接口,更重要的是它是TSSOP20封装的! 曾经在立创商城上,有个SHT30温湿度计的方案验证板,但该设计有个麻烦的地方,那就是需要另外接串口装置才能观察到MCU测量得到的SHT30温湿度数据。为此本人,决定用带这款支持USB通讯功能的STM32F0x0超值系列ARM芯片--- STM32F070F6P6,结合温湿度传感器AM2320,制作一款USB温湿度计。 它使用很简单:直接插入PC机的USB端口,然后打开串口助手之类的软件,即可观察到现场的温湿度数据。通过这个制作,大家可以学习一下AM2320的I2C和单总线的驱动方法,还有如何使用ST的Cube MX软件来实现一个USB转串口(USB TO CDC)的通信设备。 系统构架图: 系统解说:本系统有二大部分组成,分别是:支持USB通信的ARM Cortex-M0主控芯片 STM32F070F6P6和AM2320数字式温湿度传感器。 视频演示: 作品亮点 ① 无需额外仪器装置,直插到PC后运行串口助手软件即可观察到实时的温湿度数据。 ② 采用引脚紧凑、低成本、同时支持USB通信的Cortex-M0 AMR STM32F070作为主控。 ③ 使用出厂时己校准数字信号输出的AM2320作为传感器单元。插件,极易好焊接! ④ 温度分辨率是: ±0.1度,精度±0.5度;湿度分辨率: ±0.1%RH,精度:±3%RH ⑤ 提供2种演示范例,支持单总线和标准I2C 两种通信方式来驱动AM2320传感器。 ⑥ 板上STM32F070的全部I/O都被引出,可当作一个低廉的最小系统板、开发板使用。 ⑦ 本方案验证板采用USB BUS总线供电,无需额外再提供电源。 原理图分为多个部分,逐个详见分析讲解,详见“相关文件”进行下载 USB温湿度计实物展示: 软件部分的描述 限于篇幅,这里不太方便展示全部代码,比如USB通信实现和单总线、I2C总线驱动温湿度传感器AM2320等等。需要指出的是,USB通信部分,本人直接采用了ST官方出品的STM32CubeMX软件,该软件是一个基于GUI界面配置软件,通过鼠标操作芯片的配置和功能,最终该软件即可自动产生初始化代码和一个应用程序框架范例。本电子制作就是使用这个默认生成的USB转串口(USB CDC协议)应用程序,然后添加相关的温湿度采集驱动完成的。 调试过程和应用实例 按前面提供的BOM清单,正常焊接完毕后,接着把HEX烧录到ARM STM32F070F6P6芯片,即可完成准备工作。随后,将USB电缆把该PCBA电路模块和电脑链接起来(如果Windows 系统提示需要安装驱动程序,那按默认位置按照即可)。最后,打开串口助手之类的软件,即可观察到现场的温度和湿度数据。 总结 STM32F070F6P6 是一个内置USB功能、性价比很高的芯片,结合AM2320实现了比之前SHT30方案验证板更好的应用体验。该PCB板设计时,把STM32F070F6P6的全部I/O都引出了,因此,该板可当作一个低廉的最小系统板、开发板使用。如果想学习ARM Cortex-M0 芯片的应用,特别是USB总线通信的实现过程,那本文介绍的这个电子制作作品和PCB空板,是一个不错的入门选择! 基于STM32F070和AM2320的USB温湿度计实验板购买链接:https://www.szlcsc.com/product/details_97773.html
### 使用 DHT11 温湿度传感器配合 HAL 进行开发 #### 初始化和配置硬件资源 为了使 STM32 能够通过 GPIO 接口与 DHT11 通信,需先完成必要的初始化工作。这包括设置时钟、GPIO 和中断等外设参数。 ```c // 配置 GPIO 引脚用于连接 DHT11 的数据线 void MX_GPIO_Init(void) { __HAL_RCC_GPIOB_CLK_ENABLE(); // 启用 GPIOB 时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 配置 PB5 作为 DHT11 数据输入/输出 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 设置推挽输出模式 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } ``` #### 编写函数来读取 DHT11 数据 接下来定义一个专门用来获取来自 DHT11 原始测量值的功能模块。此部分涉及到了具体协议细节以及位操作技巧[^3]。 ```c uint8_t dht_data[5]; int read_DHT11_Data() { uint8_t i,j; int retry=0; while(HAL_GPIO_ReadPin(DHT_PORT,DHT_PIN)==0 && retry<100)retry++; //等待DHT准备好发送数据 if(retry>=100)return -1; for(i=0;i<5;i++)dht_data[i]=0; //启动信号 HAL_GPIO_WritePin(DHT_PORT,DHT_PIN,GPIO_PIN_RESET); HAL_Delay(18); HAL_GPIO_WritePin(DHT_PORT,DHT_PIN,GPIO_PIN_SET); for (i=0;i<40;i++) { while(!HAL_GPIO_ReadPin(DHT_PORT,DHT_PIN)); //等待高电平到来 Delay_us(30); //延时一段时间后判断高低电平状态决定是0还是1 if(HAL_GPIO_ReadPin(DHT_PORT,DHT_PIN)) dht_data[i/8]|=(1<<(7-(i%8))); while(HAL_GPIO_ReadPin(DHT_PORT,DHT_PIN)); } return check_crc(); } bool check_crc(){ unsigned char crc=0; for(int i=0;i<4;i++){ crc+=dht_data[i]; } return crc==dht_data[4]?true:false; } ``` 上述代码实现了对 DHT11 设备的一次完整查询流程,并且包含了简单的校验机制以确保接收到的信息准确性。当一切正常运作之后,则可以进一步解析这些原始字节得到实际环境条件下的相对湿度百分比及摄氏度数值[^1]。 #### 解析并展示温湿度信息 最后一步是从之前获得的五个字节数组 `dht_data[]` 中提取有用的部分转换成人类可理解的形式打印出来或上传至云端平台。 ```c float humidity, temperature; if(read_DHT11_Data()==OK){ humidity=dht_data[0]+((float)dht_data[1])/10; temperature=dht_data[2]+((float)dht_data[3])/10; printf("Humidity=%.1f%%\n",humidity); printf("Temperature=%.1f°C\n",temperature); }else{ printf("Error reading data from sensor.\n"); } ``` 这段程序片段负责将二进制形式表示的湿度温度量转化为浮点型变量以便后续处理或是直接呈现给用户查看。
评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值