【51单片机篇】DHT11温湿度传感器

一、时序分析

1.检测模块是否存在

a : dht = 1

b :dht = 0延时30ms

c: dht = 1在60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!

#include "reg52.h"
#include <intrins.h>

sbit ledOne = P3^7;
sbit dht = P3^3;

void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void Delay60us()		//@11.0592MHz
{
	unsigned char i;

	i = 25;
	while (--i);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void check_DHT()//DHT11时序图分析
{
	//a:dht = 1
	dht = 1;
	//b:dht = 0
	dht = 0;
	//延时30ms
	Delay30ms();
	//c:dht = 1
	dht = 1;
	//在60us后读取d点,如果d点是低电平(被模块拉低),说明模块存在!
	Delay60us();
	if(dht == 0){
		ledOne = 0;//亮灯说明模块存在
	}
}

void main()
{
	Delay1000ms();
	Delay1000ms();
	ledOne = 1;
	check_DHT();
	while(1);
}

 

 2.读取DHT11数据时序分析

a : dht = 1

b :dht = 0延时30ms

c: dht = 1卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht) 卡g点:while(!dht) 有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平1

DHT11传输0的时序分析
DHT11传输1的时序分析

 二、编程示例

1.温湿度通过串口传到PC显示

#include "reg52.h"
#include <intrins.h>

sbit ledOne = P3^7;
sbit dht = P3^3;
sfr AUXR = 0x8E;

char datas[5];

void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;
	SCON = 0x40;//配置串口工作方式1,REN不使能接收
	TMOD &= 0x0F;
	TMOD |= 0x20;//配置定时器1工作方式为8位自动重装
	TH1 = 0xFD;
	TL1 = 0xFD;//9600波特率初值
	TR1 = 1; //启动定时器1
}

void sendByte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);
	TI = 0;
}

void sendString(char *str)
{
	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void Delay40us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}

void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void Delay60us()		//@11.0592MHz
{
	unsigned char i;

	i = 25;
	while (--i);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void DHT11_Start()//DHT11时序图分析
{
	dht = 1;
	dht = 0;
	//延时30ms
	Delay30ms();
	dht = 1;
	//卡d点:while(dht1);卡e点while(!dht);卡f点:while(dht)
	while(dht);
	while(!dht);
	while(dht);
}

void Read_Data_From_DHT()
{
	int i;//轮
	int j;//每一轮读多少次
	char tmp;
	char flag;
	
	DHT11_Start();
	for(i=0;i<5;i++){
		for(j=0;j<8;j++){
			while(!dht);//等待卡g点
			Delay40us();
			if(dht == 1){
				flag = 1;
				while(dht);
			}else{
				flag = 0;
			}
			tmp <<= 1;
			tmp |= flag;
		}
		datas[i] = tmp;
	}
}

void main()
{
	ledOne = 1;
	UartInit();
	Delay1000ms();
	Delay1000ms();
	while(1){
		Delay1000ms();
		Read_Data_From_DHT();
		
		sendString("H:");
		sendByte(datas[0]/10 +0x30);
		sendByte(datas[0]%10 +0x30);
		sendByte('.');
		sendByte(datas[1]/10 +0x30);
		sendByte(datas[1]%10 +0x30);
		sendString("\r\n");
		
		sendString("T:");
		sendByte(datas[2]/10 +0x30);
		sendByte(datas[2]%10 +0x30);
		sendByte('.');
		sendByte(datas[3]/10 +0x30);
		sendByte(datas[3]%10 +0x30);
		sendString("\r\n");
	}
}

 

 2.温湿度检测小系统:温湿度数据在LCD1602显示

#include "reg52.h"
#include <intrins.h>

#define databuffer  P0//定义8位数据线,P0端口组

sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
sbit D5 = P3^7;
sbit D6 = P3^6;
sbit dht = P3^3;
sfr AUXR = 0x8E;

char datas[5];
char temp[8];
char huma[8];

void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;
	SCON = 0x40;//配置串口工作方式1,REN不使能接收
	TMOD &= 0x0F;
	TMOD |= 0x20;//配置定时器1工作方式为8位自动重装
	TH1 = 0xFD;
	TL1 = 0xFD;//9600波特率初值
	TR1 = 1; //启动定时器1
}

void sendByte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);
	TI = 0;
}

void sendString(char *str)
{
	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void Delay40us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}

void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void Delay60us()		//@11.0592MHz
{
	unsigned char i;

	i = 25;
	while (--i);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Check_Busy()
{
	char tmp = 0x80;
	databuffer = 0x80;
	
	while(tmp & 0x80){//比较最高位
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		EN = 1;
		_nop_();
		_nop_();
		tmp = databuffer;
		EN = 0;
		_nop_();
	}
}

void Write_Cmd_Func(char cmd)//写指令,RS低电平 
{
	Check_Busy();
	RS = 0;
	RW = 0;
	EN = 0;
	_nop_();//空函数,延时1us
	databuffer = cmd;
	_nop_();
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}

void Write_Data_Func(char cmd)//写数据,RS高电平
{
	Check_Busy();
	RS = 1;
	RW = 0;
	
	EN = 0;
	_nop_();//空函数,延时1us
	databuffer = cmd;
	_nop_();
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}

void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 27;
	j = 226;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}

void DHT11_Start()//DHT11时序图分析
{
	dht = 1;
	dht = 0;
	//延时30ms
	Delay30ms();
	dht = 1;
	//卡d点:while(dht1);卡e点while(!dht);卡f点:while(dht)
	while(dht);
	while(!dht);
	while(dht);
}

void Read_Data_From_DHT()
{
	int i;//轮
	int j;//每一轮读多少次
	char tmp;
	char flag;
	
	DHT11_Start();
	for(i=0;i<5;i++){
		for(j=0;j<8;j++){
			while(!dht);//等待卡g点
			Delay40us();
			if(dht == 1){
				flag = 1;
				while(dht);
			}else{
				flag = 0;
			}
			tmp <<= 1;
			tmp |= flag;
		}
		datas[i] = tmp;
	}
}

void LCD1602_showLine(char row,char col,char *string)
{
	switch(row){
		case 1:
			Write_Cmd_Func(0x80+col);
			while(*string){
				Write_Data_Func(*string);
				string++;
			}
			break;
		case 2:
			Write_Cmd_Func(0x80+0x40+col);
			while(*string){
				Write_Data_Func(*string);
				string++;
			}
			break;
	}
}

void LCD1602_Init()
{
	//1.延时15ms
	Delay15ms();
	//2.写指令38H(不检测忙信号)
	Write_Cmd_Func(0x38);
	//3.延时5ms
	Delay5ms();
	//4.以后每次写指令,读/写数据操作均需要检测忙信号
	//5.写指令38H:显示模式设置
	Write_Cmd_Func(0x38);
	//6.写指令08H:显示关闭
	Write_Cmd_Func(0x08);
	//7.写指令01H:显示清屏
	Write_Cmd_Func(0x01);
	//8.写指令06H:显示光标移动设置
	Write_Cmd_Func(0x06);
	//9.写指令0CH:显示开及光标设置
	Write_Cmd_Func(0x0c);
}

void Build_Datas()
{
	huma[0] = 'H';
	huma[1] = datas[0]/10 +0x30;
	huma[2] = datas[0]%10 +0x30;
	huma[3] = '.';
	huma[4] = datas[1]/10 +0x30;
	huma[5] = datas[1]%10 +0x30;
	huma[6] = '%';
	huma[7] = '\0';
	
	temp[0] = 'T';
	temp[1] = datas[2]/10 +0x30;
	temp[2] = datas[2]%10 +0x30;
	temp[3] = '.';
	temp[4] = datas[3]/10 +0x30;
	temp[5] = datas[3]%10 +0x30;
	temp[6] = 'C';
	temp[7] = '\0';
}

void main()
{
	Delay1000ms();
	UartInit();
	LCD1602_Init();
	Delay1000ms();
	Delay1000ms();
	D5 = 0;
	while(1){
		Delay1000ms();
		Read_Data_From_DHT();
		if(datas[2] > 31){
			D6 = 0;
		}
		Build_Datas();
		sendString(huma);
		sendString("\r\n");
		sendString(temp);
		sendString("\r\n");
		LCD1602_showLine(1,2,huma);
		LCD1602_showLine(2,2,temp);
	}
}

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: 好的,下面是 51 单片机读取 DHT11 湿度传感器的代码示例: #include <reg51.h> #include <intrins.h> sbit DHT11_Data = P1^0; unsigned char DHT11_Rx_Byte() { unsigned char i, dat; dat = 0; for (i=0; i<8; i++) { while(!DHT11_Data); _nop_(); _nop_(); dat <<= 1; if(DHT11_Data) { dat |= 1; } while(DHT11_Data); } return dat; } void main() { unsigned char humi_int, humi_deci, temp_int, temp_deci, check; while(1) { DHT11_Data = 1; _nop_(); _nop_(); DHT11_Data = 0; _nop_(); _nop_(); DHT11_Data = 1; while(!DHT11_Data); while(DHT11_Data); humi_int = DHT11_Rx_Byte(); humi_deci = DHT11_Rx_Byte(); temp_int = DHT11_Rx_Byte(); temp_deci = DHT11_Rx_Byte(); check = DHT11_Rx_Byte(); if((humi_int + humi_deci + temp_int + temp_deci) == check) { // 数据校验正确,可以使用 humi_int、humi_deci、temp_int 和 temp_deci 变量中的数据 } else { // 数据校验错误,不能使用 humi_int、humi_deci、temp_int 和 temp_deci 变量中的数据 } } } 该代码实现了 51 单片机读取 DHT11 湿度传感器的功能。它首先向 DHT11 发送信号,然后通过调用 DHT11_Rx_Byte 函数接收 DHT11 发送回来的数据。最后,它还进行了数据校验,确保数据的准确性。 希望这能帮 ### 回答2: 以下是51单片机读取DHT11湿度传感器的示例代码: #include <reg51.h> sbit DHT11_PIN = P1^0; // 定义DHT11信号引脚 void delay_us(unsigned int t) // 微秒级延时函数 { while (t--) { // 通过经验值估算延时时间 for(int i=0; i<11; i++); } } void delay_ms(unsigned int t) // 毫秒级延时函数 { while (t--) { delay_us(1000); } } void start_signal() // 发送起始信号 { DHT11_PIN = 0; delay_ms(20); DHT11_PIN = 1; delay_us(30); } unsigned char read_byte() // 读取一个字节的数据 { unsigned char byte = 0; for (int i = 0; i < 8; i++) { while(!DHT11_PIN); // 等待高电平信号过去 delay_us(30); if(DHT11_PIN) { byte |= (1 << (7 - i)); // 高位在前,低位在后 } while(DHT11_PIN); // 等待低电平信号过去 } return byte; } void main() { unsigned char temperature, humidity; while(1) { start_signal(); while(!DHT11_PIN); // 等待DHT11的响应信号 while(DHT11_PIN); // 等待DHT11的响应信号过去 if(DHT11_PIN) { temperature = read_byte(); // 读取度值的整数部分 read_byte(); // 读取度值的小数部分 humidity = read_byte(); // 读取湿度值的整数部分 read_byte(); // 读取湿度值的小数部分 // 打印湿度值 // ... // 进行其他操作 // ... } delay_ms(2000); // 2秒钟后重新读取湿度值 } } 以上代码是使用51单片机读取DHT11湿度传感器数据的一个示例。其中,通过定义DHT11_PIN为P1^0来指定DHT11信号引脚。通过起始信号和读取字节的函数来与DHT11进行通信。最后,通过打印湿度值或进行其他操作来处理传感器数据。整个过程会附带一些延时函数来确保正确的通信和操作时序。 ### 回答3: 51单片机读取DHT11湿度传感器的代码如下: #include <reg51.h> sbit DHT11_DATA = P1^0; void delay_us(unsigned int t) { while(t--) { _nop_(); } } unsigned char read_byte() { unsigned char i, dat; for(i = 0; i < 8; i++) { while(!DHT11_DATA); delay_us(30); if(DHT11_DATA) { dat |= (1 << (7 - i)); while(DHT11_DATA); } else { while(!DHT11_DATA); } } return dat; } void read_DHT11(unsigned int *temp, unsigned int *humi) { unsigned char i, dat[5]; DHT11_DATA = 0; delay_us(20000); DHT11_DATA = 1; delay_us(30); if(!DHT11_DATA) { while(!DHT11_DATA); while(DHT11_DATA); for(i = 0; i < 5; i++) { dat[i] = read_byte(); } if(dat[0] + dat[1] + dat[2] + dat[3] == dat[4]) { *humi = dat[0]; *temp = dat[2]; } } } void main() { unsigned int temperature, humidity; read_DHT11(&temperature, &humidity); // 处理湿度数据 while(1); } 以上代码首先定义了51单片机的引脚和一些延时函数。read_byte()函数用来读取DHT11传感器发送的数据,根据数据位的高低电平判断是0还是1,并将数据保存在变量dat中。read_DHT11()函数用来读取DHT11传感器的湿度数据,并将其保存在变量temp和humi中。主函数调用read_DHT11()函数获取湿度数据,并进行后续处理。 请注意,以上代码仅供参考,具体的湿度传感器型号和引脚连接可能会有所不同,请根据实际情况进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿gao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值