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 
",rec_dat[0],rec_dat[1]);
		printf("Temp:%d.%d °C
",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 != '')
    {
        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

猜你喜欢

转载自blog.csdn.net/m0_67390963/article/details/125056968