锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

STM32delay延时函数不准确,无法读取DHT11数据的问题

时间:2023-10-11 20:37:00 gd温湿度传感器

STM32delay延迟函数不准确,不能读取DHT11数据的问题
环境:KEIL5 、STM32F103C8T6 、 淘宝提供的例程
功能需求:stm32f103单片机读取dht温湿度数据11
问题发生我的项目中移植了商家提供的驱动包后,只有DHT11传感器不能正常工作,其他传感器可以正常工作。初步分析是DHT11驱动代码有问题。DHT对微秒的延迟要求较高。
在这里插入图片描述

问题查找:
1、经过debug调试,发现代码在if(DHT11_DATA_IN() == Bit_RESET)这里判断后,条件不成立,问题应该是DHT11_DATA_IN() 函数中。


DHT11_DATA_IN()函数的宏定义,函数功能是读取DHT11响应信号,说明DHT11没有正常启动,所以没有返回信号。

2.在程序中与波特率115200发送字节a,(大约0.0086ms),delay(50)毫秒延迟时,发现两次延迟时间大于50毫秒(约80毫秒)ms)
3.推测:1。芯片时钟可能有问题,可能性小 2、delay函数不准确,博客上有相关说法 3.我的程序可能定义了中断,但我忘记了,所以有延迟。

4.找到解决方案
我在相关的淘宝店找到了很多程序源代码,但都用了很多delay函数,网上论坛代码也是,使用不能参考。

在博客上发现可以通过while(…)替代相关函数的函数delay()函数,那就可以不用考虑delay()函数是否准确。

5.替代函数分析
MCU发送开始信号和DHT11响应函数

发送起始信号后,通过while来替代两个应答的delay()函数
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0);//跳过DHT11响应时间
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1);//跳过DHT11测量时间

相似的


到此,delay延迟不准确的问题基本解决,当数量仍然不准确时,可以调整上面的问题DelauUsaa(40);函数中的值,直到数据能够测量。上面的函数是判断接收的数据是1还是0。

dht11.c的代码

#include "dht11.h"   //DHT11初始化函数 //DHT11 DATA---PB3   void Dht11_Init(void) { 
        GPIO_InitTypeDef GPIO_InitStruct;  //开B组时钟和AFIO时钟  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);   //初始化IO口          //定义结构体变量  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;   ///配置为泄漏输出  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;     //选择管脚3  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;   ///输出速度为2MHZ  GPIO_Init( GPIOB, &GPIO_InitStruct);

	GPIO_WriteBit(GPIOB,  GPIO_Pin_0, Bit_SET);
	
	DelayMs(1000);											//延时1s越过不稳定状态
}





/* * 函数名:DHT11_Mode_IPU * 描述 :使DHT11-DATA引脚变为上拉输入模式 * 输入 :无 * 输出 :无 */
static void DHT11_Mode_IPU(void)
{ 
        
 	  GPIO_InitTypeDef GPIO_InitStructure;

	  	/*选择要控制的DHT11_PORT引脚*/	
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

	   /*设置引脚模式为浮空输入模式*/ 
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 

	  /*调用库函数,初始化DHT11_PORT*/
	  GPIO_Init(GPIOB, &GPIO_InitStructure);	 
}

/* * 函数名:DHT11_Mode_Out_PP * 描述 :使DHT11-DATA引脚变为推挽输出模式 * 输入 :无 * 输出 :无 */
static void DHT11_Mode_Out_PP(void)
{ 
        
 	GPIO_InitTypeDef GPIO_InitStructure;

	 	/*选择要控制的DHT11_PORT引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	

	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	/*调用库函数,初始化DHT11_PORT*/
  	GPIO_Init(GPIOB, &GPIO_InitStructure);	 	 
}




//MCU发送开始信号函数
void Mcu_Send_Start_Sign(void)
{ 
        
    DHT11_Mode_Out_PP();
	GPIO_WriteBit(GPIOB,  GPIO_Pin_0, Bit_RESET);
	DelayMs(18);									//拉低总线18ms以上
	GPIO_WriteBit(GPIOB,  GPIO_Pin_0, Bit_SET);		//拉高总线等待DHT11响应
    DHT11_Mode_IPU();
}

//等待DHT11响应函数
//返回值 1---响应失败 0-----响应成功
u8 Dht11_Ack(void)
{ 
        
	u8 i = 0;
	while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1)
	{ 
        
		i++;
		DelayUs(1);
		if(i>50)
		{ 
        
			return 1;			//Dht11响应失败
		}
	}
	//代码运行到这里代表DHT11响应成功
	while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0);//跳过DHT11响应时间
	while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1);//跳过DHT11测量时间

	return 0;					//DHT11响应成功
}

//读DHT11测到的数据

u8 Read_Dht11_Data(void)
{ 
        
	u8 i,data = 0;
	for(i=0;i<8;i++)
	{ 
        
		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0);//跳过数据的1bit低电平开始位
		DelayUs(40);
// data = data<<1;
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1)		//数据1
		{ 
        
            while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1);//跳过数据'1'的剩余高电平时间
// data |= 1;
            data|=(uint8_t)(0x01<<(7-i));
		}
    else{ 
        
            data&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
        }
		
	}
	return data;
}

u8 Mcu_Control_Dht11(u8 *p)
{ 
        
	u8 ret;
	Mcu_Send_Start_Sign();			//发送开始信号
	ret = Dht11_Ack();
	if(ret)
	{ 
        
		return 1;					//测量失败
	}
	p[0] = Read_Dht11_Data();	//湿度整数数据
	p[1] = Read_Dht11_Data();	//湿度小数数据
	p[2] = Read_Dht11_Data();	//温度整数数据
	p[3] = Read_Dht11_Data();	//温度小数数据
	p[4] = Read_Dht11_Data();   //8bit校验和
	
	if(p[0]+p[1]+p[2]+p[3] != p[4])
	{ 
        
		return 1;					//测量失败
	}
    
	return 0;						//测量成功
}

dht11.h的代码

#ifndef _DHT11_H_ //防止头文件重定义
#define _DHT11_H_

#include "stm32f10x.h"
#include "delay.h"


static void DHT11_Mode_IPU(void);
static void DHT11_Mode_Out_PP(void);
void Dht11_Init(void);
u8 Mcu_Control_Dht11(u8 *p);







#endif




锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章