基于51单片机 的DHT11温湿度控制系统

目录

一、 项目功能概述

二、仿真图片

 三、程序

一、 项目功能概述


1、显示温湿度
2、按键设置温湿度上下限
3、温度高于温度上限,温度过高电机启动,进行降温
4、温度低于温度下限,温度过低电机启动,进行升温
5、湿度高于湿度上限,湿度过高电机启动,进行降湿
6、湿度低于湿度下限,湿度过低电机启动,进行加湿
7、显示时间

资料下载地址:基于51单片机的DHT11温湿度控制系统

二、仿真图片

刚上电时第一行显示时间,第二行显示采集到的温湿度

温湿度报警上下限设置界面

 三、程序

部分程序



/*******************************************************************************
* 函 数 名         : delay_ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : cnt
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void delay_ms(unsigned int cnt)   //
{
	unsigned int x;
	for( ; cnt>0; cnt--)
	{
		for(x=110; x>0; x--);//软件延时为1MS
	}
}
#if 0
void delay_us(unsigned int cnt)   //
{
	while(cnt--);
}
#endif
/******************************************************
** 函数名:time_init
** 描述  :定时器初始化
** 输入  :无
** 输出  :无
******************************************************/
void time_init(void)
{
	  TMOD |= 0x01;//time0 工作方式为1
	  TH0 = 0xf8;//装载初值
	  TL0 = 0x2f;//装载初值,为2ms(65535-63535)
      TR0 = 1;//开启定时器
	  ET0 = 1;//打开中断
	  EA=1;
}
/******************************************************
** 函数名:key_scan
** 描述  :按键扫描
** 输入  :无
** 输出  :无
******************************************************/
void key_scan(void)
{
	static unsigned char key_in_flag = 0;//按键按下标志
	unsigned char key_l;//存储扫描到行列值。
	key_value = 20;//按键值清除
	if((P3 & 0x0f) != 0x0f)//按键按下
	{
		delay_ms(1);//按键消抖动
		if(((P3 & 0x0f) != 0x0f) && (key_in_flag == 1))
		{
			key_in_flag = 0;//松手检测防止一直触发
			P3 = 0x0f;
            //delay_ms(1);//按键消抖动
			key_l = P3;//扫描得到按键值
			switch(key_l)
			{
				//获取按键值
				case 0x0e:
				{
					key_value = 1;
				}
				break;
				case 0x0d:
				{
					key_value = 2;
				}
				break;
				case 0x0b:
				{
					key_value = 3;
				}
				break;
				//case 0x70:
				//break;
			}
		}
	}
	else
	{
		key_in_flag = 1;//(按键松开标志)
	}

}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : u8com
* 输    出         : 无
*******************************************************************************/
void lcd_wri_com(unsigned char com)	  //写入命令
{
	E = 0;	 //使能清零
	RS = 0;	 //选择写入命令
	RW = 0;	 //选择写入

	DB = com;
	delay_ms(1);

	E = 1;	 //写入时序
	delay_ms(5);
	E = 0;
}

/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : u8dat
* 输    出         : 无
*******************************************************************************/

void lcd_wri_data(unsigned char dat)//写入数据
{
	E = 0;	  //使能清零
	RS = 1;	  //选择写入数据
	RW = 0;	  //选择写入
	DB = dat;
	delay_ms(1);
	E = 1;	  //写入时序
	delay_ms(5);
	E = 0;
}
/*******************************************************************************
* 函 数 名         : WriString
* 函数功能		   : 刷新屏幕显示
* 输    入         : hang,add,*p
* 输    出         : 无
*******************************************************************************/
void wri_string(unsigned char y,unsigned char x,unsigned char *p)
{
	if(y==1)//如果选择第一行
		lcd_wri_com(0x80+x);//选中地址
	else
		lcd_wri_com(0xc0+x);//选中地址
		while(*p)
		{
			lcd_wri_data(*p);//写入数据
			p++;
		}
}
/*******************************************************************************
* 函 数 名         : lcd_write_char
* 函数功能		   :
* 输    入         :
* 输    出         : 无
*******************************************************************************/
void lcd_write_char(unsigned char y, unsigned char x, unsigned char dat) //列x=0~15,行y=0,1
{
	unsigned char temp_l, temp_h;
	if(y==1)//如果选择第一行
		lcd_wri_com(0x80+x);//选中地址
	else
		lcd_wri_com(0xc0+x);//选中地址
	temp_l = dat % 10;
    temp_h = dat / 10;
    lcd_wri_data(temp_h + 0x30);          //convert to ascii
    lcd_wri_data(temp_l + 0x30);
}
/*********************光标控制***********************/
void lcd1602_guanbiao(unsigned char y, unsigned char x,unsigned char on_off)
{
	if(on_off == 1)   //开光标
	{
		if(y==1)//如果选择第一行
		lcd_wri_com(0x80+x);
	    else
		lcd_wri_com(0xc0+x);//将光标移动到秒个位
		lcd_wri_com(0x0f);//显示光标并且闪烁
	}
	else
	{
        if(y==1)//如果选择第一行
		lcd_wri_com(0x80+x);
	    else
		lcd_wri_com(0xc0+x);//将光标移动到秒个位
		lcd_wri_com(0x0c);   //关光标
	}
}

/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/
void lcd_init(void)						  //LCD初始化子程序
{
	lcd_wri_com(0x38);//置功能8位双行
	lcd_wri_com(0x0c);//显示开关光标
	lcd_wri_com(0x06);//字符进入模式屏幕不动字符后移
	delay_ms(5);//延时5ms
	lcd_wri_com(0x01);  //清屏
	wri_string(1,0,times);//初始化显示
	wri_string(1,6,date);
	wri_string(2,0,"H:   %RH T:   C ");//初始化显示
}
void DHT11_delay_us(unsigned char n)
{
    while(--n);
}

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

void DHT11_start()
{
   Data=1;
   DHT11_delay_us(2);
   Data=0;
   DHT11_delay_ms(30);   //延时18ms以上
   Data=1;
   DHT11_delay_us(30);
}


void AlarmJudge(void)
{
	if(temp_value>AlarmTH)// 温度是否过高
	{
		LedTH_P=0;
		LedTL_P=1;
	}
	else if(temp_value<AlarmTL)// 温度是否过低
	{
		LedTL_P=0;
		LedTH_P=1;
	}
	else// 温度正常
	{
		LedTH_P=1;
		LedTL_P=1;
	}

	if(humi_value>AlarmHH)// 湿度是否过高
	{
		LedHH_P=0;
	  	LedHL_P=1;
	}
	else if(humi_value<AlarmHL)	// 湿度是否过低
	{
		LedHL_P=0;
		LedHH_P=1;
	}
	else	// 湿度正常
	{
		LedHH_P=1;
		LedHL_P=1;
	}

	if((LedHH_P==0)||(LedHL_P==0)||(LedTH_P==0)||(LedTL_P==0)) 	// 蜂鸣器判断,只要至少1个报警灯亮,蜂鸣器就报警
	{
		for(i=0;i<3;i++)
		{
			beep=0;
			delay_ms(20);
			beep=1;
			delay_ms(20);
		}
	}
}

/******************************************************
 ** 函数名:key_service
 ** 描述  :按键服务函数
 ** 输入  :无
 ** 输出  :无
 ** 调用  :主程序
******************************************************/

/******************************************************
 ** 函数名:alm
 ** 描述  :定时闪烁函数
 ** 输入  : 无
 ** 输出  :无
 ** 调用  :中断调用
 ******************************************************/
void time_service(void)
{
		if(time_100ms_flag)
		{
			time_100ms_flag = 0;
            if (++cnt_500ms>5)
            {
                    cnt_500ms = 0;
                    if(now_window == normal_mode)
                    {
                        EA = 0;
                        DHT11_receive();
                        EA = 1;
                        lcd_write_char(2,2,humi_value);
												lcd_write_char(2,11,temp_value);
                        AlarmJudge();//报警函数
                    }
            }

		}

}

/******************************************************
 ** 函数名:init_all_hardware
 ** 描述  :初始化所有硬件,及其变量参数。
 ** 输入  :无
 ** 输出  :无
 ** 调用  :主程序
 ******************************************************/
void init_all_hardware(void)
{
   		 
		time_init();//定时器初始化
		lcd_init();
		lcd_write_char(2,2,humi_value);
		lcd_write_char(2,11,temp_value);
		lcd_wri_com(0xcd);
		lcd_wri_data(0xdf);
		key_value = 20;
		now_window = normal_mode;
		cnt_100ms = 0;
		time_100ms_flag = 0;
        curr_menu = 0;
}
void main(void)
{
	 get_1302(time_1302);//获取时间
	 change(); //时间转换
	 init_all_hardware();//初始化硬件,IO和定时器
	 while(1)
	 {
		 get_1302(time_1302);//获取时间
		 change(); //时间转换
		 key_scan();//按键扫描
		 key_service();//按键服务处理函数
		 time_service();//时间处理函数
	 }
}
 /******************************************************
 ** 函数名:time0_interrupt
 ** 描述  :按键扫描函数
 ** 输入  :无
 ** 输出  :无
 ******************************************************/
void time0_interrupt() interrupt 1
{
	   TF0 = 0;//清除标志
	   TR0 = 0;
	   if (++cnt_100ms>50)
	   {
			cnt_100ms = 0;
			time_100ms_flag = 1;
	   }
	   TR0 = 1;
	   TH0 = 0xf8;
	   TL0 = 0x2f;//装载初值2ms(65535-63535)
}


//DS1302相关函数
/*==========================================
       D S 1 3 0 2  初 始 化
===========================================*/

void init_1302(uchar *time)
{uchar i, add;
 //uchar time_bcd[7];
 add=0x80;//0写入,1读出
 w_1302(0x8e,0x00);
 for(i=0;i<7;i++)
  {w_1302(add,*time);
   add+=2;
   time++;
   }
 w_1302(0x8e,0x80);
}

//===========================
//    读取当前时间
//===========================

void get_1302(uchar time[])
{uchar i;
 uchar add=0x81;
 w_1302(0x8e,0x00);
 for(i=0;i<7;i++)
 { 
   time[i]=r_1302(add); 
   add+=2;
   }
 w_1302(0x8e,0x80);
}    
/*=================================
   DS1302写入一个字节(上升沿有效)
=================================*/

void write_ds1302(uchar dat)
{uchar i;
 datbyte=dat;
 for(i=0;i<8;i++)
 {T_IO=datbyte0;
  T_CLK=1;
  T_CLK=0;
  datbyte=datbyte>>1;
  }
}

/*=======================================
   DS1302读取一个字节(下降沿有效)
=======================================*/

uchar read_ds1302(void)
{uchar i;
 
 for(i=0;i<8;i++)
  {datbyte=datbyte>>1;
   datbyte7=T_IO;
   T_CLK=1;
   T_CLK=0;
   }
 return(datbyte);
}

/*=========================================
         指定位置读取数据
=========================================*/

uchar r_1302(uchar add)
{uchar temp,dat1,dat2;
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 write_ds1302(add);
 temp=read_ds1302();
 T_CLK=1;
 T_RST=0;
 dat1=temp/16;
 dat2=temp%16;
 temp=dat1*10+dat2;
 return(temp);
}

/*==========================================
        指定位置写入数据
==========================================*/

void w_1302(uchar add,uchar dat)
{
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 write_ds1302(add);
 write_ds1302(dat/10<<4|dat%10);
 T_CLK=1;
 T_RST=0;
}
//DS1302数值转换
void change()
{ 
 // 时 间 的 转 换
  times[0]=time_1302[2]/10+'0';
  times[1]=time_1302[2]%10+'0';
  times[2]=':';
  times[3]=time_1302[1]/10+'0';
  times[4]=time_1302[1]%10+'0';
//  times[5]=':';
//  times[6]=time_1302[0]/10+'0';
//  times[7]=time_1302[0]%10+'0';
	times[5]='\0';
  // 日 期 的 转 换
	date[0]='2';
	date[1]='0';
  date[2]=time_1302[6]/10+'0';
  date[3]=time_1302[6]%10+'0';
  date[4]='/';
  date[5]=time_1302[4]/10+'0';
  date[6]=time_1302[4]%10+'0';
  date[7]='/';
  date[8]=time_1302[3]/10+'0';
  date[9]=time_1302[3]%10+'0';
	date[10]='\0';
}

  • 3
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

森旺电子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值