stm32-DHT11原理及代码解读

目录

一、基础知识

1.功能:温湿度检测

2.应用范围

3.硬件电路连接

二、底层代码原理分析

1.基础知识

1.单总线说明

2.单总线传送数据位定义

3.数据格式

4.校验位数据定义

2.代码分析

1.数据时序图

2.数据传输步骤


一、基础知识

1.功能:温湿度检测

        测量范围湿度:湿度:5-95%RH        精度:(±5)%RH

                          温度:-20-60℃        精度:(±2)℃

2.应用范围

        暖通空调、除湿器、农业、冷链仓储、测试及检测设备、消费品、汽车、自动控制、数据记录器、气 象站、家电、湿度调节器、医疗、其他相关湿度检测控制。

3.硬件电路连接

        1.VDD 供电 3.3~5.5V DC

        2.DATA 串行数据,单总线

        3.NC 空脚

        4.GND 接地,电源负极

 注意点:

        1. 建议连接线长度短于 5m 时用 4.7K 上拉电阻,大于 5m 时根据实际情况降低上拉电 阻的阻值。

        2. 使用 3.3V 电压供电时连接线尽量短,接线过长会导致传感器供电不足,造成测量偏差。

        3. 每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取 2 次,但不建议连续多次 读取传感器,每次读取传感器间隔大于 2 秒即可获得准确的数据。

4. 电源部分如有波动,会影响到温度。如使用开关电源纹波过大,温度会出现跳动。

二、底层代码原理分析

1.基础知识

1.单总线说明

        DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线 完成。它们是主从结构,只有主机呼叫从机时,从机才能应答。

2.单总线传送数据位定义

        DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先出

3.数据格式

        8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据 + 8bit 校验位。

        注:其中湿度小数部分为 0。

4.校验位数据定义

        “8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据”8bit 校验位等于 所得结果的末 8 位

2.代码分析

1.数据时序图

        用户主机(MCU)发送一次开始信号后,DHT11 从低功耗模式转换到高速模式,待主机开始信号结束 后,DHT11 发送响应信号,送出 40bit 的数据,并触发一次信采集。信号发送如图所示。

         注:主机从 DHT11 读取的温湿度数据总是前一次的测量值,如两次测间隔时间很长,请连续读两次以 第二次获得的值为实时温湿度值。

2.数据传输步骤

​​​        步骤一二三准备步骤即初始化。步骤四发送数据。

步骤一

        DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境 温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的 DATA 引脚处于输入状态,时刻检测外部信号。       

 步骤二:

        上图中主机发送信号:

        微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms), 然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变 ,等待 DHT11 作出回答信号,发送信号如图所示:

        由此得到代码:

        DHT11_IO_OUT();设置为引脚输出模式的函数,写个函数(简单)或直接宏定义寄存器操作(简洁);DHT11_IO_IN()同理;

        DHT11_DQ_OUT();即引脚输出高电平,可以用位带操作宏定义一番;DHT11_DQ_IN();同理;

void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
    DHT11_IO_IN();
​}

步骤三:

        DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA 引脚处于输出状态,输出 83 微秒的低电平作为应答信号紧接着输出 87 微秒的高电平通知外设准备接 收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒 的高电平后的数据接收,发送信号如 图所示:

         DHT11输出,主机接收所以配置输入模式。

        由此得到代码:

        两个while循环一个检测低电平一个检测高电平。retry其实就是高低电平时间。

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();	 
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}

步骤四:

        由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0” 的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74 微秒的高电平。位数据“0”、“1”格式信号如图所示

        通过对比得到0,1不同处在于高低电平时间

        所以我们先等度过低电平,高电平到来然后延时40us,此时如果他是低电平,那接收到的数据就是0,如果是高电平那他就是1。

//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_DQ_IN)//等待变为低电平
	while(!DHT11_DQ_IN)//等待成为高电平
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)
        return 1;
	else 
        return 0;		   
}

        根据前文:“一次传送 40 位数据,高位先出。”我们优化代码:

u8 DHT11_Read_Byte(void)
{
    u8 dat1,dat2=0;
    for(data1=0x80;data1!=0;data1>>1)
    {

        if(DHT11_Read_Bit())
           data2|=data1;
         else
            data2&=~data1;

    }  
    return data2;  
}

步骤五:结束信号

        DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 54 微秒后转为输入状态,由于上拉电阻随 之变为高电平。但 DHT11 内部重测环境温湿度数据,并记录数据,等待外部信号的到来。

        根据上文校验位结构:“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据”8bit 校验位等于 所得结果的末 8 位。

        得出代码

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;	    
}

        我们最终顺其自然的得到主函数

int main(void)
{
		u8 temper;  	    
		u8 humi;
		u8 temp;
		delay_init();
		DHT11_Init();
        oled_init();
		while(1)			
		{
			temp = DHT11_Read_Data(&temper,&humi);
			if(temp ==0)
			{
				OLED_ShowNum(10,10,humi,5,16);
                OLED_ShowNum(10,30,temper,5,16);
			}
					
		};
}

基于温度湿度一体的传感器DHT11 以下是在51单片机上测试成功的代码 #include<at89x52.h> #include<intrins.h>//加上这句下面的 _nop_();就能用 bit xianshiqiehuan; // sbit dht11_dat=P1^6; //开发板用 sbit dht11_dat=P2^0; //使用版用 unsigned char c,count, dht11temp,dht11dat; unsigned char dht11value[5]; unsigned int x,y,z; unsigned char code dat[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,}; delay() { unsigned char a; for(a=200;a>0;a--); } display(unsigned char x) //使用版用 { P0=dat[(x0)/10];//十位 P2_3=0; delay(); P2_3=1; P0=dat[(x0)];//个位 P2_2=0; delay(); P2_2=1; } /*display(unsigned char x) //开发板用 { P0=dat[(x0)/10];//十位 P1_2=0; delay(); P1_2=1; P0=dat[(x0)];//个位 P1_3=0; delay(); P1_3=1; } */ delay_1s() { unsigned int i=50000; while(i--); } delay_10us() //10us { _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); } void delayms(unsigned char x) //1ms单位延时程序 { unsigned char j; while(x--) { for(j=0;j<123;j++){;} } } read_dht11() { unsigned char i; dht11_dat=1; _nop_(); //起始 dht11_dat=0;//总线 delayms(18);//手册要求大于18ms dht11_dat=1;//高总线等待dht11回应 while(dht11_dat); // 等待dht11回应 若有回应 dht11_dat=0;往下执行 while(!dht11_dat);//回应后dht11将总线80us,过后又将总线高,进入下一步 while(dht11_dat); //高80us 又变,往下执行 进入50us延时 for(i=0;i<24;i++) { while(!dht11_dat);//50us过后...... dht11_dat=1;往下执行 delay_10us();delay_10us();delay_10us();//延时30us,查看总线是高是dht11temp=0; //先默认为0处理 if(dht11_dat) dht11temp=1; //1处理 dht11dat=dht11dat<<1; //必须先移动再或 若先或再移本次数据就移动了 dht11dat=dht11dat|dht11temp; dht11value[i/8]=dht11dat; while(dht11_dat);//如果处理的是1,30us过后总线还是1,那就在此等待总线变为0进入下一个50us电平,不然会重复进行0处理 } } main() { delay_1s(); //要求上电等1秒,让dht11稳定 EA=1;//开放中断 TMOD=0x01;//设T0 为16位计数方式 ET0=1;//定时0中断允许 TR0=1;//开启TR0 while(1) { if(!xianshiqiehuan) //显示温度 display(dht11value[2]) ; else {display(dht11value[0]) ; //显示湿度 P0=0x92&0x7f; //千位显 S.代表湿度 P2_5=0; delay(); P2_5=1; } } } dingshi() interrupt 1 //定时器0服务程序 { TH0=0; TL0=0; count++; if(count==55){count=0;read_dht11();xianshiqiehuan=~xianshiqiehuan; } //在切换显示时采集,以防中断采样带来的显示闪烁 }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式小趴菜学习记录

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

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

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

打赏作者

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

抵扣说明:

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

余额充值