STM32/GD32 驱动 DHT11例程

发布于:2025-07-15 ⋅ 阅读:(17) ⋅ 点赞:(0)

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。

以下为.c代码,有效解决了再量产过程中部分温湿度读取不到数据和上电后不能立即读取到温湿度数据的代码:

#include "dht11.h"
u8 ReceiveState;
u8 HIT_WorkOkFlag;
u8  rcv_buf[5];
u8  bit1;//暂存接收位
double HIT10_Humidity;
double HIT10_Temperature;
u8 Counter;

//PB3=CLK  PB4 SDA
void HIT10_IIC_Init(void)
{					     
   rcu_periph_clock_enable(RCU_GPIOA);   // 初始化 GPIOC 时钟
	 gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_8); // 初始化为输出模式
//	 gpio_bit_set(GPIOA, GPIO_PIN_8);   // 引脚初始电平为低电平
	
	IIC_SDA_High;
	HIT10_Humidity = 0;
	HIT10_Temperature = 0;
}




void HIT10_SDA_OUT()
{
   rcu_periph_clock_enable(RCU_GPIOA);   // 初始化 GPIOC 时钟
	 gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_8); // 初始化为输出模式
//	 gpio_bit_set(GPIOA, GPIO_PIN_8);   // 引脚初始电平为低电平
}

void HIT10_SDA_IN()
{
   rcu_periph_clock_enable(RCU_GPIOA);   // 初始化 GPIOC 时钟
	 gpio_init(GPIOA, GPIO_MODE_IPU,   GPIO_OSPEED_10MHZ , GPIO_PIN_8); // 初始化为输入模式
//	 gpio_bit_set(GPIOA, GPIO_PIN_8);   // 引脚初始电平为低电平
}

//DHT11读取
void  read_AHT10_once(void)
{

	u8 Sum;
	rcv_buf[0] = 0;//清零
	u8 i,j;
	u32 n;
	u32 LowVoltageTimeCounter;
	u32 HighVoltageTimeCounter;
	j=5;
	
	ReceiveState=0;
	HIT10_SDA_OUT();
	IIC_SDA_High;delay_us(10);
	IIC_SDA_Low ;	delay_ms(2);
	HIT10_SDA_IN();
	delay_us(10);
	ReceiveState=1;
	
	if(ReceiveState==1)
	{
		n=160;
		Counter =0;
		while((READ_SDA==0)&&(n>0))
		{
			delay_us(1);
			n--;
			Counter++;
		}
		if(READ_SDA==1)ReceiveState = 2;
  }
	
  if(ReceiveState==2)
	{
		n=160;
		Counter =0;
		while((READ_SDA==1)&&(n>0))
		{
			delay_us(1);
			n--;
			Counter++;
		}
		if(READ_SDA==0)ReceiveState = 3;
  }
	
  if(ReceiveState==3)
	{
		//数据有效
		while(j--)
		{
				for(i=0; i<8; i++)
				{
					n=160;
					LowVoltageTimeCounter =0;
					while((READ_SDA==0)&&(n>0))
					{
						delay_us(1);
						n--;
						LowVoltageTimeCounter++;
					}
					
					n=160;
					HighVoltageTimeCounter =0;
					while((READ_SDA==1)&&(n>0))
					{
						delay_us(1);
						n--;
						HighVoltageTimeCounter++;
					}
					
					if(HighVoltageTimeCounter>LowVoltageTimeCounter)bit1 = 1;
					else bit1 =0; 

						rcv_buf[j]<<=1;
						rcv_buf[j]|=(u8)bit1;
				 } 
		 }
	 }
	
	
	Sum = rcv_buf[4]+rcv_buf[3]+rcv_buf[2]+rcv_buf[1];
	if((rcv_buf[0] == Sum)&&(Sum!=0))	   //校验
	{
			 HIT10_Humidity= rcv_buf[4];//湿度
			 HIT10_Temperature = rcv_buf[2];//温度
		   HIT_WorkOkFlag = 0;
  }
  else
	{
		   HIT_WorkOkFlag= HIT_WorkOkFlag + 1;
	}
		
  //连续5秒都没读上来	
	if(HIT_WorkOkFlag>=10)
	{	
		HIT10_Humidity = 38;
		HIT10_Temperature = 22;
	}
}




以下是.h文件:

#ifndef __DHT11_H
#define __DHT11_H
#include "sys.h"
#include "delay.h"	
//extern  u8 HIT10_Temperature;
//extern  u8 HIT10_Humidity;

#define  DeleyParameter   delay_us(10)

#define  READ_SDA         gpio_input_bit_get(GPIOA, GPIO_PIN_8)

#define  IIC_SDA_Low      gpio_bit_reset(GPIOA, GPIO_PIN_8)
#define  IIC_SDA_High     gpio_bit_set(GPIOA, GPIO_PIN_8)

////IO操作函数	 
extern void  read_AHT10_once(void);
extern void HIT10_IIC_Init(void);
extern double HIT10_Humidity;
extern double HIT10_Temperature;
extern u8 HIT_WorkOkFlag;

#endif

微妙延时会对dht11的时序影响,因此需要使用模拟的us延时来适用所有芯片以及不同的工作频率。延时如下:


#define SYSCLK_MHZ    (SystemCoreClock/1000000) //系统时钟频率
 
/**********************************************
//MYI2C_Delay_us
**********************************************/
void  delay_us(unsigned long nTim)
{
	uint32_t Tdata = nTim*SYSCLK_MHZ/5;
	for(uint32_t i=0;i<Tdata;i++)
	{
		__NOP();	__NOP();	__NOP();
	}
}

 不保证所有芯片都可以用,但是99%的芯片通过调整Nop个数可以解决,这里是您主板延时读取不到温湿度的解决办法。


网站公告

今日签到

点亮在社区的每一天
去签到