基于51单片机的智能窗帘设计

一、项目功能概述

1、使用DHT11获取温湿度

2、使用光照强度传感器检测环境光照

3、通过红外遥控器切换自动模式和手动模式。

        自动模式时,当环境中湿度小于60%、温度大于20、光照强烈时,电机自动转动。

        手动模式时,通过遥控器控制电机启动或停止。

4、LCD1602显示相关数据

资料下载地址:基于51单片机智能窗帘设计

二、仿真图片

自动模式

手动模式

 

三、程序


/*******************************************************************************
* 函 数 名         : 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(2,0,times);//初始化显示
	wri_string(2,6,date);
	wri_string(1,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);
}

unsigned char DHT11_rec_byte()      //接收一个字节
{
   unsigned char i,dat=0;
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {
      while(!Data);   等待50us低电平过去
      DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(Data==1)    //数据为1时,使dat加1来接收数据1
         dat+=1;
      while(Data);  //等待数据线拉低
    }
    return dat;
}

void DHT11_receive()      //接收40位的数据
{
    unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
    DHT11_start();
    if(Data==0)
    {
        while(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;
        }
        humi_value = RH;
        temp_value = TH;
    }
}


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);
//		}
//	}
}





void key_handle(void)
{
	if(key_value == 1)
	{
		 mode = 0;
		 wri_string(2,12,"Auto");//初始化显示
	}
	if(key_value == 2)
	{
		 mode = 1;
		 wri_string(2,12,"Manu");//初始化显示
	}
	if(key_value == 3)
	{
		if(motor_mode == 0)
		{
			motor_mode = 1;
		}
		else
		{
			motor_mode = 0;
		}
	}
	
}



/******************************************************
 ** 函数名:key_service
 ** 描述  :按键服务函数
 ** 输入  :无
 ** 输出  :无
 ** 调用  :主程序
******************************************************/
void key_service(void)
{
    switch (now_window)
    {
           case  normal_mode:
           {
              if (key_value == 1)
              {
                    now_window = set_mode;
                    curr_menu = 0;
                    wri_string(1,0,"T:  -           ");//初始化显示
                    wri_string(2,0,"H:  -           ");//初始化显示
                    lcd_write_char(1,2,AlarmTL);
										lcd_write_char(1,6,AlarmTH);
                    lcd_write_char(2,2,AlarmHL);
										lcd_write_char(2,6,AlarmHH);
                    lcd1602_guanbiao(1,3,1);
              }
           }
           break;
           case  set_mode:
           {
                    if (key_value == 1)
                    {
                            ++curr_menu;
                            if (curr_menu==1)
                            {
                                lcd1602_guanbiao(1,7,1);
                            }
                            else if(curr_menu==2)
                            {
                                lcd1602_guanbiao(2,3,1);
                            }
                            else if(curr_menu==3)
                            {
                                lcd1602_guanbiao(2,7,1);
                            }
                            if(curr_menu>3)
                            {
                                curr_menu = 0;
                                lcd1602_guanbiao(2,7,0);
                                now_window = normal_mode;
                                wri_string(2,0,times);//初始化显示
																wri_string(2,6,date);
															  wri_string(2,0,"                    ");//初始化显示
																wri_string(1,0,"H:   %RH T:   C ");//初始化显示
																lcd_write_char(1,2,humi_value);
																lcd_write_char(1,11,temp_value);
//																lcd_wri_com(0xcd);
//																lcd_wri_data(0xdf);
                            }
                    }
                    if (key_value == 2)
                    {
                            if(curr_menu==0)
                            {
                                 if(++AlarmTL>99)
                                 {
                                     AlarmTL = 0;
                                 }
                                 lcd_write_char(1,2,AlarmTL);
                                 lcd1602_guanbiao(1,3,1);
                            }
                            else if (curr_menu==1)
                            {
                                 if(++AlarmTH>99)
                                 {
                                     AlarmTH = 0;
                                 }
                                 lcd_write_char(1,6,AlarmTH);
                                 lcd1602_guanbiao(1,7,1);
                            }
                            else if(curr_menu==2)
                            {
                                if(++AlarmHL>99)
                                 {
                                     AlarmHL = 0;
                                 }
                                 lcd_write_char(2,2,AlarmHL);
                                 lcd1602_guanbiao(2,3,1);
                            }
                            else if(curr_menu==3)
                            {
                                 if(++AlarmHH>99)
                                 {
                                     AlarmHH = 0;
                                 }
                                 lcd_write_char(2,6,AlarmHH);
                                 lcd1602_guanbiao(2,7,1);
                            }
                    }
                    if (key_value == 3)
                    {
                            if(curr_menu==0)
                            {
                                 if(--AlarmTL<0)
                                 {
                                     AlarmTL = 99;
                                 }
                                 lcd_write_char(1,2,AlarmTL);
                                  lcd1602_guanbiao(1,3,1);
                            }
                            else if (curr_menu==1)
                            {
                                 if(--AlarmTH<0)
                                 {
                                     AlarmTH = 99;
                                 }
                                 lcd_write_char(1,6,AlarmTH);
                                 lcd1602_guanbiao(1,7,1);
                            }
                            else if(curr_menu==2)
                            {
                                if(--AlarmHL<0)
                                 {
                                     AlarmHL = 99;
                                 }
                                  lcd_write_char(2,2,AlarmHL);
                                   lcd1602_guanbiao(2,3,1);
                            }
                            else if(curr_menu==3)
                            {
                                if(--AlarmHH<0)
                                 {
                                     AlarmHH = 99;

                                 }
                                 lcd_write_char(2,6,AlarmHH);
                                  lcd1602_guanbiao(2,7,1);
                            }
                    }
           }
           break;
    }
}
/******************************************************
 ** 函数名: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(1,2,humi_value);
												lcd_write_char(1,11,temp_value);
                        AlarmJudge();//报警函数
                    }
            }

		}

}
void main(void)
{

	 init_all_hardware();//初始化硬件,IO和定时器
	 while(1)
	 {
		 
		 key_scan();//按键扫描
		 key_handle();
		
		 time_service();//时间处理函数
		 Get_Light();
		
	 }
}

  • 5
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

森旺电子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值