蓝桥杯:第四届初赛—“模拟智能灌溉系统”

目录

问题自行解决:(自己写的过程中)

1、(DS1302实时时钟)自动状态(L1亮),按下S6进入温度阈值设定界面。(按下可以             进入,但松开就返回实时时钟)

错误写法:(直接写在while里)

正确写法:(写在按键里)

 2、继电器:手动状态(L2亮),按下S5,继电器打开;按下S4,继电器关闭。(按下S5           可以打开继电器,但松开就关闭)

错误写法:

正确写法:(与问题1相同)

 参考代码:

存在问题的代码分析:(要同时操作蜂鸣器与继电器,一定要列出所有情况!!!)


注意:先把每个模块调通,再写逻辑程序!!!

问题自行解决:(自己写的过程中)

1、(DS1302实时时钟)自动状态(L1亮),按下S6进入温度阈值设定界面。(按下可以进入,但松开就返回实时时钟)

错误写法:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

实时时钟显示不能写while循环里面!!!!

写在按键里面:(注意条件)

unsigned char key_num = 0, key_num2 = 0;(初始状态均为零)

key_num:0自动状态 / 1手动状态

key_num2:②进入界面 / ③控制蜂鸣器 / ④阈值+1 / ⑤打开灌溉 / ⑥阈值-1 / ⑦关闭灌溉

正确写法:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

 

 2、继电器:手动状态(L2亮),按下S5,继电器打开;按下S4,继电器关闭。(按下S5可以打开继电器,但松开就关闭)

错误写法:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

 ③watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

 正确写法:(与问题1相同)

(写在主函数while里面发出嗡嗡怪声?)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

 参考代码:

#include "reg52.h"
#include "ds1302.h"
#include "iic.h"

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned char SMG_duanma[19] = {
	//  0   1    2    3    4    5    6    7
		0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
	//  8   9    A10  B11  C12  D13  E14  F15
		0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
	// -16  .17
		0xbf,0x7f,0xff};  //共阳数码管
unsigned char yi, er, san, si, wu, liu, qi, ba;

unsigned char DS1302_Read_add[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//DS1302读地址
unsigned char DS1302_Write_add[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//DS1302写地址
//  08时30分00秒
unsigned char Timer[7] = {0x00,0x30,0x08,0x14,0x02,0x01,0x22};
//                         秒   分   时   日   月   星期  年 

unsigned char Rb2;//阻值
unsigned char SD;//湿度
unsigned char YZ;//湿度阈值

unsigned char key7 = 0;//S7键值(0:自动状态 1:手动状态)
unsigned char key6 = 0;//S6键值(0:阈值调整 1:保存阈值)
unsigned char key5 = 0;//S5键值(1:阈值+1)
unsigned char key4 = 0;//S4键值(1:阈值-1)
unsigned char fmq = 1;//蜂鸣器功能默认打开(就是蜂鸣器可以开关)(0:功能关闭,蜂鸣器不能操作)
unsigned char jdq = 0;//继电器默认关闭

void eeprom_write(unsigned pos,unsigned char dat);

void InitHC138(unsigned char n)
{
	switch (n)
	{
		case 4://LED
			P2 = (P2 & 0x1f) | 0x80;
		break;
		case 5://蜂鸣器与继电器
			P2 = (P2 & 0x1f) | 0xa0;
		break;
		case 6://数码管位置
			P2 = (P2 & 0x1f) | 0xc0;
		break;
		case 7://数码管段码
			P2 = (P2 & 0x1f) | 0xe0;
		break;
		case 0://不选
			P2 = (P2 & 0x1f) | 0x00;
		break;
	}
}

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

/*===================系统初始化==========================================
关闭LED、蜂鸣器与继电器

========================================================================*/
void InitSystem()
{
	InitHC138(4);//上电后为自动状态L1亮
	P0 = 0xfe;
	InitHC138(5);
	P0 = 0x00;
}

/*=================数码管单元==========================================
初始:08:30(DS1302)
=====================================================================*/
void SMG_Bit(unsigned pos, unsigned char dat)
{
	InitHC138(7);
	P0 = 0xff;//消影
	
	InitHC138(6);
	P0 = 0x01 << pos;
	InitHC138(7);
	P0 = dat;
}

void SMG_All(unsigned char dat)
{
	InitHC138(6);
	P0 = 0xff;
	InitHC138(7);
	P0 = dat;
}

void ShowSMG()
{
	SMG_Bit(0, SMG_duanma[yi]);
	Delayms(1);
	SMG_Bit(1, SMG_duanma[er]);
	Delayms(1);
	SMG_Bit(2, SMG_duanma[san]);
	Delayms(1);
	SMG_Bit(3, SMG_duanma[si]);
	Delayms(1);
	SMG_Bit(4, SMG_duanma[wu]);
	Delayms(1);
	SMG_Bit(5, SMG_duanma[liu]);
	Delayms(1);
	SMG_Bit(6, SMG_duanma[qi]);
	Delayms(1);
	SMG_Bit(7, SMG_duanma[ba]);
	Delayms(1);
	
	SMG_All(0xff);//数码管最后一位太亮
}

/*=================按键单元============================================
S7:工作状态切换键 自动/手动
①手动工作状态下:
S6:按下关闭蜂鸣器提醒功能,再次按下打开功能。循环
S5:打开灌溉
S4:关闭灌溉
②自动工作状态下:
S6:按下进入湿度阈值调整界面:--,再次按下将阈值保存到EEPROM中,并退出设定界面
S5:阈值+1
S4:阈值-1
=====================================================================*/

void ScanKeys()
{
//按键S7	
	if (S7 == 0)//上电初始为自动状态
	{
		Delayms(5);
		if (S7 == 0)
		{//key7:0自动状态  1手动状态
			if (key7 == 0)
			{
				key7 = 1;//手动状态L2
				InitHC138(4);
				P0 = 0xfd;
			}
			else if (key7 == 1)
			{
				key7 = 0;//自动状态L1
				InitHC138(4);
				P0 = 0xfe;
			}
		}
		while(!S7)
		{
			ShowSMG();
		}
	}
//按键S6	
	if (S6 == 0)
	{
		Delayms(5);
		if (S6 == 0)
		{
				if (key7 == 0)//自动状态
				{
						if (key6 == 0)//阈值调整界面
						{key6 = 1;}
						else if (key6 == 1)//阈值保存
						{key6 = 0;}
				}
				else if (key7 == 1)//手动状态:开关蜂鸣器(蜂鸣器默认是打开状态)
				{	
						if (fmq == 1)
						{
							fmq = 0;//(S6按下,蜂鸣器状态关闭,不可操作)
						}
						else if (fmq == 0)
						{
							fmq = 1;
						}
				}
		}
		while(!S6)
		{
			ShowSMG();
		}
	}
//按键S5	
	if (S5 == 0)//自动:+1   手动:打开继电器
	{
		Delayms(5);
		if (S5 == 0)
		{
			if (key7 == 0)//自动状态
			{
				key5 = 1;//阈值+1
			}
			else if (key7 == 1)//手动状态
			{
				jdq = 1;//打开继电器
			}
		}
		while(!S5)
		{
			ShowSMG();
		}
	}
//按键S4	
	if (S4 == 0)//自动:-1   手动:关闭继电器
	{
		Delayms(5);
		if (S4 == 0)
		{
			if (key7 == 0)//自动状态
			{
				key4 = 1;//阈值-1
			}
			else if (key7 == 1)//手动状态
			{
				jdq = 0;//关闭继电器
			}
		}
		while(!S4)
		{
			ShowSMG();
		}
	}
}

/*=================实时时钟DS1302======================================
初始:08:30(DS1302)
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
=====================================================================*/
void DS1302_Init()//初始化时钟
{
	unsigned char i;
	
	Write_Ds1302_Byte(0x8e,0x00);//允许写(写保护)
	for (i = 0; i < 7; i++)
	{
		Write_Ds1302_Byte(DS1302_Write_add[i],Timer[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);//禁止写
}

void DS1302_ReadTime()//读时间
{
	unsigned char i;
	
	for (i = 0; i < 7; i++)
	{
		Timer[i] = Read_Ds1302_Byte(DS1302_Read_add[i]);
	}
}

/*=================AD湿度检测==========================================
void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
=====================================================================*/
unsigned char ReadAD(unsigned char AIN)
{
	unsigned char temp;//临时变量
	
	IIC_Start();
	IIC_SendByte(0x90);//允许写
	IIC_WaitAck();
	IIC_SendByte(AIN);//写通道
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);//允许读
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_Stop();
	
	return temp;
}

/*=================EEPROM存储器(读、写)===============================
void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
=====================================================================*/
unsigned char eeprom_read(unsigned char add)//从某地址读数据
{
	unsigned char dat;//数据
	
	IIC_Start();
	IIC_SendByte(0xa0);//允许写
	IIC_WaitAck();
	IIC_SendByte(add);//写通道
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0xa1);//允许读
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_Stop();
	
	Delayms(5);//延时(防止连读、连写出错)
	return dat;//数据
}

void eeprom_write(unsigned pos, unsigned char dat)//向某地址写数据
{
	IIC_Start();
	IIC_SendByte(0xa0);//允许写
	IIC_WaitAck();
	IIC_SendByte(pos);//写通道
	IIC_WaitAck();
	IIC_SendByte(dat);//写数据
	IIC_WaitAck();
	IIC_Stop();
	Delayms(5);//延时(防止连读、连写出错)
}

//=========================主函数===================================================
void main()
{	
	InitSystem();
	DS1302_Init();
	yi = 0; er = 8; san = 16; si = 3;
	wu = 0; liu = 18; qi = 0; ba = 0;
	
//	eeprom_write(0x10,50);
/*初始阈值为50(写入存储器)但是写在这里有问题:每次上电初始化阈值都是50.
	解决:上电一次,50存入后,注释掉,从此不再初始写入50,后续继续从此地址
	读出更改后的阈值*/
	YZ = eeprom_read(0x10);//从存储器读阈值(初始阈值=50)
	
	while(1)
	{
		DS1302_ReadTime();//实时时钟
		Rb2 = ReadAD(3);//(读滑动变阻器)123
		SD = Rb2 * 0.39; // 0.39*255 = 99.45
		
		ScanKeys();
		
		if (key7 == 0)//自动状态
		{
			
			if (SD < YZ)//湿度<阈值
			{
				InitHC138(5); P0 = 0x10;//打开继电器
			}
			else if (SD >= YZ)//湿度>阈值
			{
				InitHC138(5);	P0 = 0x00;//关闭继电器
			}
			
			if (key6 == 1)//阈值界面调整
			{
				if (key5 == 1)
				{
					key5 = 0;//释放状态
					YZ = YZ + 1;
				}
				if (key4 == 1)
				{
					key4 = 0;//释放状态
					YZ = YZ - 1;
				}
				yi = 16; er = 16; san = 18; si = 18; wu = 18; liu = 18;
				qi = YZ / 10; ba = YZ % 10;
			}
			else if (key6 == 0)//阈值保存
			{
				eeprom_write(0x10,YZ);
				yi = Timer[2]/16; er = Timer[2]%16; san = 16; //08时
				si = Timer[1]/16; wu = Timer[1]%16; liu = 18; //30分
				qi = SD / 10; ba = SD % 10; //湿度
			}	
		}
		
		
		else if (key7 == 1)//手动状态
		{
//①湿度<阈值 蜂鸣器功能没开(手动关闭)			
			if ((SD < YZ) && (fmq == 0))
			{
					if (jdq == 1)//打开继电器(fmq没开)
					{
						InitHC138(5);
						P0 = 0x10;
					}
					else if (jdq == 0)//关闭继电器(fmq没开)
					{
						InitHC138(5);
						P0 = 0x00;
					}
			}
//②湿度<阈值 蜂鸣器功能打开(湿度小了,蜂鸣器打开)			
			if ((SD < YZ) && (fmq == 1))
			{
					if (jdq == 1)//打开继电器(fmq打开)
					{
						InitHC138(5);
						P0 = 0x50;
					}
					else if (jdq == 0)//关闭继电器(fmq打开)
					{
						InitHC138(5);
						P0 = 0x40;
					}
			}
//③湿度>阈值 蜂鸣器一定是关闭的 
			if (SD > YZ)
			{
					if (jdq == 1)//打开继电器(fmq关闭)
					{
						InitHC138(5);
						P0 = 0x10;
					}
					else if (jdq == 0)//关闭继电器(fmq关闭)
					{
						InitHC138(5);
						P0 = 0x00;
					}
			}
			yi = Timer[2]/16; er = Timer[2]%16; san = 16;
			si = Timer[1]/16; wu = Timer[1]%16; liu = 18;
			qi = SD / 10; ba = SD % 10;
		}
		
		ShowSMG();
	}
}

存在问题的代码分析:(要同时操作蜂鸣器与继电器,一定要列出所有情况!!!)

/*存在问题:继电器正常工作,蜂鸣器不正常工作
	S6:控制蜂鸣器的开关
	S5:打开继电器(打开后:P0=0x10; 按S6:P0=0xfmq  不可能同时工作)
	S4:关闭继电器
所以:写出蜂鸣器与继电器的所有状态!!!!
			①湿度>阈值 蜂鸣器一定是关闭的(继电器可开、关)
			②湿度<阈值 蜂鸣器 功能打开(叫)(S6可关)/功能关闭(不叫);继电器可开、关
*/	

	else if (key7 == 1)//自动状态
	{
			if (fmq == 0)//蜂鸣器打开
			{
					InitHC138(5);
					P0 = 0x40;
			}
			else if (fmq == 1)//蜂鸣器关闭
			{
					InitHC138(5);
					P0 = 0x00;
			}
			
			if (jdq == 0)//继电器关闭
			{
					InitHC138(5);
					P0 = 0x00;
			}
			else if (jdq == 1)//继电器打开
			{
					InitHC138(5);
					P0 = 0x10;
			}
	}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

行不地上

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

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

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

打赏作者

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

抵扣说明:

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

余额充值