通信工程毕设 基于单片机的室内温湿度自动控制系统(源码+硬件+论文)


0 前言

🔥
这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 毕业设计 基于单片机的室内温湿度自动控制系统(源码+硬件+论文)

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:4分

🧿 项目分享:见文末!

在这里插入图片描述

1 主要功能

硬件主要以STC89C52型单片机为核心,通过1602液晶显示屏实时地显示传感器DHT11检测到的温湿度值,设定的阀值可以通过外部EEPROM存储,这实现就算没有接电源,在系统设置过的阈值也能保存在单片机系统里面。如果过阀值就会有相应的报警模块驱动。本研究设计的温湿度控制器框图如图

在这里插入图片描述

要求简述:
1.能够测量室内温度、湿度;
2.具有温度、湿度显示功能;
3.当温度低于某值时,进行升温;温度高于某值时,进行降温;
4.当湿度低于某值时,进行加湿;湿度高于某值时,进行除湿。

2 硬件设计(原理图)

在这里插入图片描述

在这里插入图片描述

3 核心软件设计

在对于所需要设计完成的课题功能有了一个总体上的概念认识之后,必须首先要设置形成一个程序框架上的功能流程图,为实现对每个功能设计划分模块,分别对模块设计完成相应的课题功能,最终再将所以子模块合理有序的设计连接起来,形成一个完整的程序。主程序首先要根据需要来为整个温湿度控制系统环境进行一个初始化,并且再把所有收集而来的各种温湿度数据指令发送到控制端。其中最为关键就是判断温湿度,要通过判断正确的温度和湿度来决定于单片机系统应该采取什么措施,然后用相应的代码来编程。主程序流程图如图

在这里插入图片描述

关键代码

#include <intrins.h>
#include <absacc.h>
#include <math.h> 
#define uchar unsigned char
#define uint unsigned int
//时间计算
#define Imax 14000    //此处为晶振为11.0592时的取值, 
#define Imin 8000    //如用其它频率的晶振时,
#define Inum1 1450    //要改变相应的取值。
#define Inum2 700 
#define Inum3 3000 
//解码变量
unsigned char Im[4]={0x00,0x00,0x00,0x00};
//全局变量
uchar f;
unsigned long m,Tc;
unsigned char IrOK;
//定义四个输出端口
sbit Led_jiashi=P3^7;		//加湿
sbit Led_qushi=P3^6;		//去湿
sbit Led_jiangwen=P3^1;		//降温
sbit Led_shengwen=P3^2;	//升温
//定义三个设置按键
sbit Key_SET = P2^0;
sbit Key_ADD = P2^1;
sbit Key_SUB = P2^2;
sbit Key_OK  = P2^3;
//定义24C02数据口
sbit SCL = P1^0;
sbit SDA = P1^1;
//定义DHT11数据口
sbit DATA = P1^7;
sbit buzz=P3^5;
//定义LCD1602端口
sbit E=P1^3;		//1602使能引脚
//sbit RW=P2^6;		//1602读写引脚	
sbit RS=P1^2;		//1602数据/命令选择引脚
//定义全局变量
uchar U8FLAG,U8temp,U8comdata,U8RH_data_H_temp,U8RH_data_L_temp,U8T_data_H_temp,U8T_data_L_temp,U8checkdata_temp;
uchar U8RH_data_H,U8RH_data_L,U8T_data_H,U8T_data_L,U8checkdata;
uchar Mode,humidity,temperature;
char TH,TL,HH,HL;
bit bdata FlagStartRH,hot,cold,humid,dry,BJ;
//定时器0初始化
void Timer0_Init()
{
	ET1 = 1;        //允许定时器0中断
	TMOD = 0x11;       //定时器工作方式选择
	TL1 = 0xb0;     
	TH1 = 0x3c;     //定时器赋予初值
	TR1 = 1;        //启动定时器 
	IT1=1;//下降沿有效
	EX1=1;//外部中断1开
	TH0=0;//T0赋初值
	TL0=0;
	TR0=0;//t0开始计时
}
//定时器1中断
void Timer1_ISR (void) interrupt 3 using 0
{
	uchar RHCounter;
	TL1 = 0xb0;
	TH1 = 0x3c;     //定时器赋予初值
	RHCounter++;
	if(RHCounter%10==0&&BJ==1)
	buzz=!buzz;
	else if(BJ==0)
	buzz=1;
	//每2秒钟启动一次温湿度转换
    if (RHCounter >= 40)
    {
       FlagStartRH = 1;
	   RHCounter = 0;
    }
}
void DELAY(unsigned int t)
{
	while(t!=0)
	t--;
}
void IICStart(void)
{
     SCL=0;  
 	 DELAY(1);
     SDA=1; SCL=1; DELAY(1);
     SDA=0; DELAY(1);
     SCL=0; 
}
void IICStop(void)
{
	 SDA=0;SCL=1; DELAY(1);
     SDA=1; DELAY(1);
     SCL=0; 	
}
void SEND0(void)
{
	SDA=0;
	SCL=1;
	DELAY(1);
	SCL=0;
}
void SEND1(void)
{
	SDA=1;
	DELAY(1);
	SCL=1;
	DELAY(1);
	SCL=0;
}

bit Check_Ack(void)
{
	unsigned char errtime=250;
	DELAY(1);
	SCL=1; 
	DELAY(1);
	CY=SDA;
	while(CY)
	{
		errtime--; 
		CY=SDA;
		if (!errtime)
		{
			IICStop();
			return 1;
		}
	}
	DELAY(1);
	SCL=0; 
	return 0;
}
void Write_byte(unsigned char dat) 
{
    unsigned char i;
	for(i=0;i<8;i++)
	{	
		if((dat<<i)&0x80)
		SEND1();
		else
		SEND0();
	}
}
unsigned char Read_byte(void)
{
	unsigned char i,temp=0;     
	for(i=0;i<8;i++)
	{
        SDA=1;
	    SCL=1;
	    DELAY(1);  
		if(SDA==1)
		{
			temp=temp<<1;
			temp=temp|0x01;
		}
		else
		temp=temp<<1;
		 SCL=0;	
	  }
	  return temp;
}
unsigned char rdeeprom(unsigned char addr)
{ 
       unsigned char temp=0;
		bit flag=0;
		IICStart();
		Write_byte(0xa0);
        Check_Ack();
		Write_byte(addr);
		Check_Ack();
		IICStart();
		Write_byte(0xa1);
		Check_Ack();
		temp=Read_byte();
		SEND1();
		IICStop();
 	    return temp;   
}  
void wrteeprom(unsigned char addr,unsigned char dat)
{
       IICStart();
		Write_byte(0xa0);
		Check_Ack();
		Write_byte(addr);
		Check_Ack();
		Write_byte(dat);
		Check_Ack();
		IICStop();
}
void Delay1(uint j)
{
    uchar i;
    for(;j>0;j--)
    { 	
		for(i=0;i<27;i++);
    }
} 
void  Delay_10us(void)
{
    uchar i;
    i--;
    i--;
    i--;
    i--;
    i--;
    i--;
}	
void  COM(void)
{
    uchar i;
    for(i=0;i<8;i++)	   
    {
  	    U8FLAG=2;
	   	while((!DATA)&&U8FLAG++);
		Delay_10us();
		Delay_10us();
		Delay_10us();
  		U8temp=0;
        if(DATA)U8temp=1;
		    U8FLAG=2;
		while((DATA)&&U8FLAG++);
	   	//超时则跳出for循环		  
	   	if(U8FLAG==1)break;
	   	//判断数据位是0还是1	   
		// 如果高电平高过预定0高电平值则数据位为 1 	 
		U8comdata<<=1;
	   	U8comdata|=U8temp;        //0
    }//rof
}
uchar RH(void)
{
    //主机拉低18ms 
    DATA=0;
	Delay1(180);  //原来为5
	DATA=1;
	//总线由上拉电阻拉高 主机延时20us
	Delay_10us();
	Delay_10us();
	Delay_10us();
	Delay_10us();
	//主机设为输入 判断从机响应信号 
	DATA=1;
	//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行	  
	if(!DATA)		 //T !	  
	{
	    U8FLAG=2;
	    //判断从机是否发出 80us 的低电平响应信号是否结束	 
	    while((!DATA)&&U8FLAG++);
	    U8FLAG=2;
	    //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
	    while((DATA)&&U8FLAG++);
	    //数据接收状态		 
	    COM();
	    U8RH_data_H_temp=U8comdata;
	    COM();
	    U8RH_data_L_temp=U8comdata;
	    COM();
	    U8T_data_H_temp=U8comdata;
	    COM();
	    U8T_data_L_temp=U8comdata;
	    COM();
	    U8checkdata_temp=U8comdata;
	    DATA=1;
	    //数据校验 
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
	    if(U8temp==U8checkdata_temp)
	    {
	   	   U8RH_data_H=U8RH_data_H_temp;
	   	   U8RH_data_L=U8RH_data_L_temp;
	   	   U8T_data_H=U8T_data_H_temp;
	   	   U8T_data_L=U8T_data_L_temp;
	   	   U8checkdata=U8checkdata_temp;
	    }
		return 1;
	}
	else   //传感器不响应
	{
	   return 0;
	}
}
void delay()
{
	int i,j;
	for(i=0; i<=10; i++)
	for(j=0; j<=2; j++);
}	  	
void enable(uchar del)
{
	P0 = del;
	RS = 0;
	E = 1;
	delay();
	E = 0;
	delay();
}
void write(uchar del)
{
	P0 = del;
	RS = 1;
	E = 1;
	delay();
	E = 0;
	delay();
}
void L1602_init(void)
{
	enable(0x38);
	enable(0x0c);
	enable(0x06); 
	enable(0x01); //清屏要放在最后
}
void L1602_char(uchar hang,uchar lie,char sign)
{
	uchar a;
	if(hang == 1) a = 0x80;
	if(hang == 2) a = 0xc0;
	a = a + lie - 1;
	enable(a);
	write(sign);
}
void L1602_string(uchar hang,uchar lie,uchar *p)
{
	uchar a;
	if(hang == 1) a = 0x80;
	if(hang == 2) a = 0xc0;
	a = a + lie - 1;
	enable(a);
	while(1)
	{
		if(*p == '\0') break;
		write(*p);
		p++;
	}
}
//显示整型的温湿度数据用,共占用4位,其中一位符号位
void L1602_int(uchar hang, uchar lie, int num)
{
   uint temp;
   uint gewei,shiwei,baiwei,sign;
   if (num >= 0)
   sign = 0;
   else
   sign = 1;
   temp = abs(num);
   baiwei = temp / 100;
   temp = temp - baiwei*100;
   shiwei = temp / 10;
   gewei = temp - shiwei*10;
   num = abs(num);
   if (num>=100)
   {
   //   L1602_char(hang, lie+1, baiwei+48);  
	  L1602_char(hang, lie+2, shiwei+48);  
	  L1602_char(hang, lie+3, gewei+48);  
   }
   else if (num>=10)
   {
      if (sign == 1)	   
	  L1602_char(hang, lie+1, '-');
	  L1602_char(hang, lie+2, shiwei+48);  
      L1602_char(hang, lie+3, gewei+48);
   }
   else
   {
      if (sign == 1)	   
	  L1602_char(hang, lie+2, '-');
	  else
	  L1602_char(hang, lie+2, ' ');
      L1602_char(hang, lie+3, gewei+48);  
   }
}
void display()
{
	if(Mode==0)
	{
		L1602_int(1,3,temperature);
		L1602_char(1,7,0xdf);
		L1602_int(1,12,humidity); 
		if(hot==1&&cold==0&&humid==0&&dry==0)
		{L1602_string(2,1," It's very hot! ");BJ=1;} 
		else if(hot==1&&cold==0&&humid==1&&dry==0)
		{L1602_string(2,1," Hot and humid! ");BJ=1;}
		else if(hot==1&&cold==0&&humid==0&&dry==1)
		{L1602_string(2,1,"  Hot and dry!  ");BJ=1;}
		else if(hot==0&&cold==1&&humid==0&&dry==0)
		{L1602_string(2,1," It's very cold!");BJ=1;}
		else if(hot==0&&cold==1&&humid==1&&dry==0)
		{L1602_string(2,1," Cold and humid!");BJ=1;}
		else if(hot==0&&cold==1&&humid==0&&dry==1)
		{L1602_string(2,1,"  Cold and dry! ");BJ=1;}
		else if(hot==0&&cold==0&&humid==1&&dry==0)
		{L1602_string(2,1,"It's very humid!");BJ=1;}
		else if(hot==0&&cold==0&&humid==0&&dry==1)
		{L1602_string(2,1," It's very dry! ");BJ=1;}
		else if(hot==0&&cold==0&&humid==0&&dry==0)
		{L1602_string(2,1,"Good environment");BJ=0;}
	}									  
}
void KEY()
{
	if(Key_SET==0||(IrOK==1&&Im[2]==0x0D))
	{
		Delay1(200);
		if(Key_SET==0||(IrOK==1&&Im[2]==0x0D))
		{
			Mode++;
			IrOK=0;
			if(Mode==1)
			{
				L1602_string(1,1," TH:    C HH:  %");
				L1602_char(1,8,0xdf);
				L1602_string(2,1," TL:    C HL:  %");
				L1602_char(2,8,0xdf);
				L1602_int(1,4,TH);
				L1602_int(1,12,HH);
				L1602_int(2,4,TL);
				L1602_int(2,12,HL);
				enable(0x80+6);
				enable(0x0f);
			}
			else if(Mode==2)
			{
				enable(0x80+0x40+6);
				enable(0x0f);
			}
			else if(Mode==3)
			{
				enable(0x80+14);
				enable(0x0f);
			}
			else if(Mode==4)
			{
				enable(0x80+0x40+14);
				enable(0x0f);
			}
			else if(Mode>=5)
			{
				Mode=1;
				enable(0x80+6);
				enable(0x0f);
			}
			
			while(!Key_SET);
		}
	}
	else if(Key_ADD==0||(IrOK==1&&Im[2]==0x40))
	{
		Delay1(200);
		if(Key_ADD==0||(IrOK==1&&Im[2]==0x40))
		{
			IrOK=0;
			if(Mode==1)
			{
				TH++;
				if(TH>=100)
				TH=99;
				L1602_int(1,4,TH);
				enable(0x80+6);
			}
			else if(Mode==2)
			{
				TL++;
				if(TL>=TH)
				TL=TH-1;
				L1602_int(2,4,TL);
				enable(0x80+0x40+6);
			}
			else if(Mode==3)
			{
				HH++;
				if(HH>=100)
				HH=99;
				L1602_int(1,12,HH);
				enable(0x80+14);
			}
			else if(Mode==4)
			{
				HL++;
				if(HL>=HH)
				HL=HH-1;
				L1602_int(2,12,HL);
				enable(0x80+0x40+14);
			}
			while(!Key_ADD);
		}
	}
	else if(Key_SUB==0||(IrOK==1&&Im[2]==0x19))
	{
		Delay1(200);
		if(Key_SUB==0||(IrOK==1&&Im[2]==0x19))
		{
			IrOK=0;
			if(Mode==1)
			{
				TH--;
				if(TH<=TL)
				TH=TL+1;
				L1602_int(1,4,TH);
				enable(0x80+6);
			}
			else if(Mode==2)
			{
				TL--;
				if(TL<=0)
				TL=0;
				L1602_int(2,4,TL);
				enable(0x80+0x40+6);
			}
			else if(Mode==3)
			{
				HH--;
				if(HH<=HL)
				HH=HL+1;
				L1602_int(1,12,HH);
				enable(0x80+14);
			}
			else if(Mode==4)
			{
				HL--;
				if(HL<=0)
				HL=0;
				L1602_int(2,12,HL);
				enable(0x80+0x40+14);
			}
			while(!Key_SUB);	
		}
	}
	else if((Key_OK==0||(IrOK==1&&Im[2]==0x15))&&Mode!=0)	 
	{
		Delay1(200);
		if((Key_OK==0||(IrOK==1&&Im[2]==0x15))&&Mode!=0)
		{
			IrOK=0;
			wrteeprom(0,TH);
			Delay1(20);
			wrteeprom(1,TL);
			Delay1(20);
			wrteeprom(2,HH);
			Delay1(20);
			wrteeprom(3,HL);
			Delay1(20);
			L1602_string(1,1,"Tem:   C Hum:  %"); 
			L1602_string(2,1,"Good environment");
			Mode=0;
			enable(0x0c);
			while(!Key_OK);
		}
	}
}
//数据初始化
void Data_Init()
{
   Led_qushi = 1;
   Led_jiashi=1;
   Led_jiangwen = 1;
   Led_shengwen = 1;
}
void main()
{
    uint i, j, testnum;
    EA = 0;
	Timer0_Init();  //定时器0初始化
    Data_Init();
	EA = 1;
	L1602_init();
	L1602_string(1,1," Welcome to T&H ");
	L1602_string(2,1," Control System!");
		//延时
	for (i=0;i<1000;i++)
	   for (j=0;j<100;j++)
	   {;}
	TH=rdeeprom(0);	 
	Delay1(20);		 //加延时可以存取稳定
	TL=rdeeprom(1);
	Delay1(20);
	HH=rdeeprom(2);
	Delay1(20);
	HL=rdeeprom(3);
	Delay1(20);

	if(TH<0) 
	{
		wrteeprom(0,30);
		Delay1(20);		 //加延时可以存取稳定
		TH=rdeeprom(0);	
		Delay1(20);		 //加延时可以存取稳定
	}
	if(TL<0)
	{
		wrteeprom(1,20);
		Delay1(20);		 //加延时可以存取稳定
		TL=rdeeprom(1);
		Delay1(20);		 //加延时可以存取稳定
	}
	if(HH<0) 
	{
		wrteeprom(2,60);
		Delay1(20);		 //加延时可以存取稳定
		HH=rdeeprom(2);
		Delay1(20);		 //加延时可以存取稳定
	}
	if(HL<0)
	{
		wrteeprom(3,50);
		Delay1(20);		 //加延时可以存取稳定
		HL=rdeeprom(3);
		Delay1(20);		 //加延时可以存取稳定
	}
    //清屏
	L1602_string(1,1,"                ");
	L1602_string(2,1,"                ");
    L1602_string(1,1,"Tem:   C Hum:  %");
	L1602_string(2,1,"Good environment");
	while(1)
	{
		 if (FlagStartRH == 1)	 //温湿度转换标志检查
		 {
		     TR1 = 0;
             testnum = RH();
 			 FlagStartRH = 0;
			 TR1 = 1;
			 humidity = U8RH_data_H;	 //读出温湿度,只取整数部分
			 temperature = U8T_data_H;
			 if(Mode==0)		//温湿度控制
			 {
			 	if (temperature > TH)
				{
					Led_jiangwen = 0;
					hot=1;
					Led_shengwen = 1;
					cold=0;
			//		BJ=1;
				}
				else if(temperature<TL)
				{
					Led_shengwen = 0;
					cold=1;
					Led_jiangwen = 1;
					hot=0;
					buzz=0;
			//		BJ=1;
				}			      
				else
				{
					Led_jiangwen=1;
					Led_shengwen=1;
					hot=0;
					cold=0;
					buzz=1;
				}
				if (humidity > HH)
				{
					Led_qushi = 0;
					humid=1;
					Led_jiashi = 1;
					dry=0;
			//		BJ=1;
				}
				else if(humidity<HL)
				{
					Led_jiashi = 0;
					dry=1;
					Led_qushi = 1;
					humid=0;
			//		BJ=1;
				}		
				else
				{
					Led_qushi=1;
					Led_jiashi=1;
					humid=0;
					dry=0;
				}	
			 }
			 else
			 {
			 	Led_shengwen=1;
				Led_jiangwen=1;
				Led_jiashi=1;
				Led_qushi=1;
				hot=0;
				cold=0;
				humid=0;
				dry=0;
				BJ=0;
			 }	
		}
		display();
		KEY();
	}	
}
//外部中断解码程序_外部中断0
void intersvr1(void) interrupt 2 using 1
{
	TR0=1;
	Tc=TH0*256+TL0;//提取中断时间间隔时长
	TH0=0; 
	TL0=0;         //定时中断重新置零
	if((Tc>Imin)&&(Tc<Imax))
	{ 
		m=0;
		f=1;
		return;
	 }       //找到启始码
	 if(f==1)
	{
		if(Tc>Inum1&&Tc<Inum3) 
		{
			Im[m/8]=Im[m/8]>>1|0x80; m++; 
		}
	    if(Tc>Inum2&&Tc<Inum1) 
		{
			Im[m/8]=Im[m/8]>>1; m++; //取码
		}
		if(m==32) 
		{
			m=0;  
			f=0;
			if(Im[2]==~Im[3]) 
			{
				IrOK=1;
				TR0=0; 
			}
			else IrOK=0;   //取码完成后判断读码是否正确
		}	  //准备读下一码   
	}
}

4 实现效果

在这里插入图片描述

5 最后

包含内容

在这里插入图片描述

🧿 项目分享:见文末!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值