树梅派硬件编程_DTH11温湿度检测

DTH11使用

DTH11总线时序

在这里插入图片描述
在这里插入图片描述

DTH11与主机通信原理

主机和从机之间的通信可通过如下几个步骤完成(外设(如微处理器)读取DHT11的数据
步骤一:
  DHT11上电后(DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时DHT11的DATA引脚处于输入状态,时刻检测外部信号。
步骤二:
  微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的DATA数据线也随之变高,等待DHT11作出回答信号。
步骤三:
  DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)
后,等待87微秒的高电平后的数据接收。
步骤四:
 由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据“0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低电平加68-74微秒的高电平。

DHT11编码步骤

一. 单片机上点后1s内不读取

二. 主机(单片机)发送起始信号:
 1.主机先拉高data。
 2.拉低data延迟18ms。
 3.拉高data(通过此操作将单片机引脚设置为输入)。

三. 从机(DHT11)收到起始信号后进行应答:
 从机拉低data,主机读取到data线被拉低持续80us后从机拉高data线, 持续80us,直到高电平结束,意味着主机可以开始接受数据。

四. 主机开始接收数据:
 1.主机先把data线拉高(io设置为输入)。
  2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
  从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线电平,如果为低电平,则为“0”,如果为高电平,则为“1”。
 3.继续重复上述1,2步骤累计40次。

五. data线拉低50us代表读取结束

主要问题

在通信时,会发生无法读取(即读取bit时 DTH11无法把信号拉低的问题),这时采取判断error并重新进行发送请求操作.

通信文件

/*
 * dht11.c
 * 
 */


#include <stdio.h>
#include <wiringPi.h>
#include <time.h>
#include <stdlib.h>

#define	DTH_sense	24

typedef unsigned char uchar;

int count=0;

typedef struct {
	uchar HumInt;
	uchar HumFloat;
	uchar TemInt;
	uchar TemFloat;
}DTH_DATA;

//初始化wiringPi
void wiringPiStart(void)
{
	wiringPiSetup();
	
}

//初始化 开启DTH11
void DHT11_start()
{
	pinMode(DTH_sense, OUTPUT);
	
   digitalWrite(DTH_sense,0);
   delayMicroseconds(2);
   digitalWrite(DTH_sense,1); //发送一个高电平脉冲
   delayMicroseconds(2);
   
   digitalWrite(DTH_sense,0); //拉低延时
   delay(20);   //延时18ms以上
   
   digitalWrite(DTH_sense,1);
   delayMicroseconds(30); //主机拉高20~40us
   
   pinMode(DTH_sense, INPUT);
}

//从DTH11接收一个字节
uchar DHT11_rec_byte() 
{
   uchar i,dat={0};
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {          //每个bit之前有50us低电平
     while(digitalRead(DTH_sense)==0)
     {++count;if(count>=65536){printf("error1\n");return -1;}}; count=0;   //等待50us低电平过去
     
      delayMicroseconds(30);     //延时30us,如果还为高则数据为1,否则为0 
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(digitalRead(DTH_sense))    //数据为1时,使dat加1来接收数据1
         {dat+=1;}
         
      while(digitalRead(DTH_sense)==1)
      {++count;if(count>=100000){printf("error2\n");return -1;}};count=0;  //等待数据线拉低    
    }  
    return dat;
}

//接收40位的数据
int DHT11_receive(DTH_DATA* data)     
{
    uchar H_H=0, H_L=0, T_H=0, T_L=0,revise=0; 
    
    DHT11_start();
    
	while(digitalRead(DTH_sense)==1)
	{++count;if(count>=65536){printf("error3\n");return 0;}};count=0; 
    while(digitalRead(DTH_sense)==0);   //等待DTH拉高
	{++count;if(count>=65536){printf("error4\n");return 0;}};count=0; 
    while(digitalRead(DTH_sense)==1);  //拉高后延时80us,进入数据传输
	{++count;if(count>=65536){printf("error5\n");return 0;}};count=0; 
       
    if( (H_H=DHT11_rec_byte())==-1) return 0;    //接收湿度高八位  
    if( (H_L=DHT11_rec_byte())==-1) return 0;    //接收湿度低八位  
    if( (T_H=DHT11_rec_byte())==-1) return 0;    //接收温度高八位  
    if( (T_L=DHT11_rec_byte())==-1) return 0;    //接收温度低八位
    if( (revise=DHT11_rec_byte())==-1) return 0; //接收校正位

	if((H_H+H_L+T_H+T_L)==revise)      //校正
    {
		data->HumInt = H_H;
		data->HumFloat = H_L;
		data->TemInt = T_H;
		data->TemFloat = T_L;
     } 
	
     delayMicroseconds(25);    //结束
	return 1;
}

int main(int argc, char **argv)
{
	DTH_DATA data={0,0};
	time_t curtime;
	
	wiringPiStart();
	while(1){
		delay(2000);
		time(&curtime);
		printf("当前时间: %s",ctime(&curtime));
		
		if(!DHT11_receive(&data)) continue; 
		printf("HUM: %d.%d %% RH\n",data.HumInt,data.HumFloat);
		printf("TEM: %d.%d ^C\n",data.TemInt,data.TemFloat);
	}
	return 0;
}


输出

当前时间: Wed Jul  7 20:02:37 2021
HUM: 51.0 % RH
TEM: 27.9 ^C
当前时间: Wed Jul  7 20:02:39 2021
HUM: 51.0 % RH
TEM: 27.9 ^C
当前时间: Wed Jul  7 20:02:41 2021
HUM: 51.0 % RH
TEM: 27.8 ^C

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值