51单片机基础之DHT11温湿度传感器

接线: 

代码:

main.c文件

/*
使用DHT11模块,检测温湿度,在lcd1602上面显示,因为1602显示不是每次都能出来,所以加了串口打印,会更加直观。
*/
#include <reg51.h>
#include "lcd.h"
#include <intrins.h>
#include <stdio.h>

sbit Temp_data=P3^6;	//信号引脚

unsigned int rec_dat[4];
unsigned char rec_dat_lcd0[6];
unsigned char rec_dat_lcd1[6];
unsigned char rec_dat_lcd2[6];
unsigned char rec_dat_lcd3[6];

void DHT11_delay_us(unsigned char n);
void DHT11_delay_ms(unsigned int z);
void DHT11_start();
unsigned char DHT11_rec_byte();
void DHT11_receive();
void InitUART(void);

//主函数
void main()
{	
	InitUART();	//串口中断初始化
	P1=0xf0;
	InitLcd1602();
	LcdShowStr(0,0,"Shidu:");
	LcdShowStr(0,1,"Wendu:");

	while(1)
	{
		DHT11_delay_ms(150);
		DHT11_receive();

		//这个函数是打印字符函数,应该是起到数值转化的作用。
		sprintf(rec_dat_lcd0,"%d",rec_dat[0]);
		sprintf(rec_dat_lcd1,"%d",rec_dat[1]);
		sprintf(rec_dat_lcd2,"%d",rec_dat[2]);
		sprintf(rec_dat_lcd3,"%d",rec_dat[3]);
		DHT11_delay_ms(100);
		
		//湿度
		LcdShowStr(7,0,rec_dat_lcd0);
		LcdShowStr(9,0,".");
		LcdShowStr(10,0,rec_dat_lcd1);
		LcdShowStr(11,0," %");
		
		//温度
		LcdShowStr(7,1,rec_dat_lcd2);
		LcdShowStr(9,1,".");
		LcdShowStr(10,1,rec_dat_lcd3);
		LcdShowStr(11,1," C");
			
		//下面通过串口助手打印温度
		//我也为什么他不用中断服务函数,就可以打印,那好需要这个中断干嘛,不是可以直接打印吗?这是我的疑问。
		printf("Humi:%d.%d \n",rec_dat[0],rec_dat[1]);
		printf("Temp:%d.%d °C\n",rec_dat[2],rec_dat[3]);			
	}
}

//DHT11起始信号
void DHT11_start()	
{
	Temp_data=1;
	
	DHT11_delay_us(2);
	
	Temp_data=0;
	
	DHT11_delay_ms(20);
	
	Temp_data=1;
	
	DHT11_delay_us(13);
}

//接收一个字节
unsigned char DHT11_rec_byte()
{	
	unsigned char i,dat;	
	for(i=0;i<8;i++)
	{
			while(!Temp_data);
		  DHT11_delay_us(8);
			dat<<=1;
			if(Temp_data==1)
			{
				dat+=1;
			}
			while(Temp_data);
	}
	return dat;	
}

//接收温湿度数据
void DHT11_receive()
{
	unsigned int R_H,R_L,T_H,T_L;
	unsigned char RH,RL,TH,TL,revise;
	
	DHT11_start();
	Temp_data=1;
	if(Temp_data==0)
	{
		while(Temp_data==0);   //等待拉高     
        DHT11_delay_us(40);  //拉高后延时80us
		
        R_H=DHT11_rec_byte();    //接收湿度高八位  
        R_L=DHT11_rec_byte();    //接收湿度低八位  
        T_H=DHT11_rec_byte();    //接收温度高八位  
        T_L=DHT11_rec_byte();    //接收温度低八位
        revise=DHT11_rec_byte(); //接收校正位

        DHT11_delay_us(25);    //结束

        if((R_H+R_L+T_H+T_L)==revise)      //校正
        {
            RH=R_H;
            RL=R_L;
            TH=T_H;
            TL=T_L;
	
        } 
        /*数据处理,方便显示*/
        rec_dat[0]=RH;
        rec_dat[1]=RL;
        rec_dat[2]=TH;
        rec_dat[3]=TL;
	}	
}
//延时us   --2*n+5us
void DHT11_delay_us(unsigned char n)
{
    while(--n);
}

//延时ms
void DHT11_delay_ms(unsigned int z)
{
   unsigned int i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}

//使用定时器1作为串口波特率发生器
void InitUART(void)
{
	TMOD=0x20;					//定时器1的工作方式2
	SCON=0x40;					//串口通信工作方式1
	REN=1;						//允许接收
	TH1=0xFD,TL1=0xFD;		//波特率=9600
	TI=1;                       //这里一定要注意
	TR1=1;	
	EA = 1;                  //开总中断
}
Lcd.c文件

#include"lcd.h"

void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令
{
    //Read_Busy();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
		LCD_Delay10ms(1);
    LCD1602_EN = 1;
		LCD_Delay10ms(1);
    LCD1602_EN = 0;    
}

void Lcd1602_Write_Data(unsigned char dat)   //写数据
{
      //Read_Busy();
      LCD1602_RS = 1;
      LCD1602_RW = 0;
      LCD1602_DB = dat;
			LCD_Delay10ms(1);
      LCD1602_EN = 1;
			LCD_Delay10ms(1);
      LCD1602_EN = 0;
}
//指定位置开始显示数据!
void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示
{
    unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;//第一行开始,x表示一行的第x个
    else
        addr = 0x40 + x;//第二行开始,x表示一行的第x个
    
    Lcd1602_Write_Cmd(addr|0x80);
}

void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串
{
    LcdSetCursor(x,y);      //当前字符的坐标
    while(*str != '\0')
    {
        Lcd1602_Write_Data(*str++);
    }
}

void InitLcd1602()              //1602初始化
{
    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据
    Lcd1602_Write_Cmd(0x0c);
    Lcd1602_Write_Cmd(0x06);
    Lcd1602_Write_Cmd(0x01);    //清屏   
}

void LCD_Delay10ms(unsigned int c)   //误差 0us
{
    unsigned char a,b;
    for(;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
Lcd.h文件

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DB  P0      //data bus 数据总线
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P2^7;	 

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
//void Lcd1602_Delay1ms(uint c);   //误差 0usvo
void LCD_Delay10ms(unsigned int c);
//void Read_Busy();           //忙检测函数,判断bit7是0,允许执行;1禁止
void Lcd1602_Write_Cmd(unsigned char cmd);     //写命令
void Lcd1602_Write_Data(unsigned char dat);   //写数据
void LcdSetCursor(unsigned char x,unsigned char y);  //坐标显示
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);     //显示字符串
void InitLcd1602();              //1602初始化
					  

#endif

运行结果:

 

VID_20220410_172203

  • 19
    点赞
  • 273
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
### 回答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()函数获取湿度数据,并进行后续处理。 请注意,以上代码仅供参考,具体的湿度传感器型号和引脚连接可能会有所不同,请根据实际情况进行相应的修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值