蓝桥杯单片机第四届省赛题详细讲解(模拟智能灌溉系统)

看之前强烈建议先自己做一遍!!!
整个工程文件(有注释讲解)
网盘链接
先上演示效果

蓝桥杯单片机第五届模拟智能灌溉系统

首先依旧从赛题的系统框图开始讲起
在这里插入图片描述
首先需要做的是将系统框图里的各部分模块提前调试好,方便后续进行调试。使用IIC和DS1302的驱动,将他们复制在工程目录下,并调试好。
首先按照数码管显示要求显示时间和湿度。
在这里插入图片描述
在这里插入图片描述
顺便注意要求,湿度是由Rb2电位器产生的,时间是ds1302产生的。
主函数显示代码:

extern uchar time[7]; //ds1302.c中定义的存储时间的数组

uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管

uchar SMG_mode=0,move; //数码管模式定义,滑动变阻器Rb2定义
void main(void)
{
	init(); //初始开发板
	ds1302_init(); //uchar time[7]={0,30,8,0,0,0,0}; 8:30:00
	while(1)
	{
		get_time(); //时间获取
		move=IIC_read(0x90,0x03); //读取Rb2电阻阻值
		move=move*0.3921; //100/255 将255转换到100
		if(SMG_mode==0)
		{
			SMG[0]=time[2]/10;SMG[1]=time[2]%10;SMG[2]=21; //时间显示
			SMG[3]=time[1]/10;SMG[4]=time[1]%10;SMG[5]=20;
			SMG[6]=move/10;SMG[7]=move%10;  //显示湿度
		}
		SMG_output();
		Dkey_scan();
	}
}

然后接着看题目要求:
在这里插入图片描述
在这里插入图片描述
信息提取:
灌溉由继电器模拟

自动模式手动模式
L1点亮L2点亮
根据湿度自动灌溉通过按键控制灌溉
低于设定阈值开启继电器,高于关闭继电器低于阈值,蜂鸣器打开,使用按键s6关闭蜂鸣器

定义变量:

bit work_mode=0; //0为自动模式,1为手动模式
char threshold=50; //定义初始湿度阈值
uchar led=0xff,buzz=0x00; //定义led口和蜂鸣器继电器口,消除其他赋值干扰

手动模式与自动模式代码

		if(work_mode==0) //自动模式
		{
			led |=0x02;led &=0xfe;P2=0X80;P0=led; //打开L1,关闭L2
			if(move<threshold) //低于阈值
			{
				buzz|=0X10;P2=0XA0;P0=buzz; //打开继电器
			}
			else 
			{
				buzz&=0XEF;P2=0XA0;P0=buzz; //关闭继电器
			}
		}
		else //手动模式
		{
			led |=0x01;led &=0XFD;P2=0X80;P0=led; //打开L2,关闭L1
			if(move<threshold) //低于阈值
			{
				buzz|=0X40;P2=0XA0;P0=buzz; //打开蜂鸣器
			}
			else
			{
				buzz&=0Xbf;P2=0XA0;P0=buzz; //关闭蜂鸣器
			}
		}

然后就可以开始写按键了:
在这里插入图片描述
S7:切换自动模式和手动模式
手动模式下:
S6:关闭和打开蜂鸣器提醒功能
S5:打开灌溉
S4:关闭灌溉
自动模式下:
S6:调整阈值,且数码管显示切换,再次按下退出,且保存湿度阈值到EEPROM之中
S5:阈值加一
S4:阈值减一

代码如下:

		else if(SMG_mode==1)
		{
			SMG[0]=SMG[1]=21;SMG[3]=SMG[4]=SMG[5]=20;
			SMG[6]=threshold/10;SMG[7]=threshold%10;  //显示湿度
		}
void Dkey_scan(void)
{
	static uchar keybyte=0;
	static uchar key;
	if(((P3&0X0F)!=0X0F)&&(keybyte==0))
	{
		delay5ms();
		if((P3&0X0F)!=0X0F)
		{
			keybyte=1;key=P3&0x0f;
		}
	}
	if((keybyte==1)&&((P3&0X0F)==0X0F))
	{
		if((P3&0X0F)==0X0F)
		{
			switch(key)
			{
				case 0x0e:
					if(work_mode==0)work_mode=1;
				  else work_mode=0;
					break;
				case 0x0d:
					if(work_mode==1) //手动模式下
					{
						if(buzz_state==1){buzz_state=0;P2=0XA0;P0=0X00;} //关闭蜂鸣器
						else {buzz_state=1;}//打开蜂鸣器使能
					}
					else  //自动模式下
					{
						if(SMG_mode==0)SMG_mode=1; //切换数码管状态
						else SMG_mode=0;
					}
					break;
				case 0x0b:
					if(work_mode==1) //手动模式
					{
						buzz|=0X10;P2=0XA0;P0=buzz; //打开灌溉
					}
					else //自动模式下
					{
						threshold++; //阈值加1
						if(threshold>99)threshold=99; //范围
					}
					break;
				case 0x07:
					if(work_mode==1)//手动模式
					{
						buzz&=0XEF;P2=0XA0;P0=buzz; //关闭灌溉
					}
					else //自动模式下
					{
						threshold--; //阈值减1
						if(threshold<0)threshold=0; //范围
					}
					break;
			}
			keybyte=0;
		}
	}
}

最后就做完了。
main.c

#include <stc15f2k60s2.h>
#include "intrins.h"
#include "iic.h"
#include "ds1302.h"

#define uchar unsigned char
#define uint unsigned int

void SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Dkey_scan(void);

extern uchar time[7]; //ds1302.c中定义的存储时间的数组

uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管

uchar SMG_mode=0,move; //数码管模式定义,滑动变阻器Rb2定义
bit work_mode=0; //0为自动模式,1为手动模式
char threshold=50; //定义初始湿度阈值
uchar led=0xff,buzz=0x00; //定义led口和蜂鸣器继电器口,消除其他赋值干扰

bit buzz_state=1; //为1打开蜂鸣器,为0关闭蜂鸣器
void main(void)
{
	init(); //初始开发板
	ds1302_init(); //uchar time[7]={0,30,8,0,0,0,0}; 8:30:00
	threshold=IIC_read(0xA0,0x00); //上电读取EEPROM
	while(1)
	{
		get_time(); //时间获取
		move=IIC_read(0x90,0x03); //读取Rb2电阻阻值
		move=move*0.3921; //100/255 将255转换到100
		if(SMG_mode==0)
		{
			SMG[0]=time[2]/10;SMG[1]=time[2]%10;SMG[2]=21; //时间显示
			SMG[3]=time[1]/10;SMG[4]=time[1]%10;SMG[5]=20;
			SMG[6]=move/10;SMG[7]=move%10;  //显示湿度
		}
		else if(SMG_mode==1)
		{
			SMG[0]=SMG[1]=21;SMG[3]=SMG[4]=SMG[5]=20;
			SMG[6]=threshold/10;SMG[7]=threshold%10;  //显示湿度
		}
		if(work_mode==0) //自动模式
		{
			led |=0x02;led &=0xfe;P2=0X80;P0=led; //打开L1,关闭L2
			if(move<threshold) //低于阈值
			{
				buzz|=0X10;P2=0XA0;P0=buzz; //打开继电器
			}
			else 
			{
				buzz&=0XEF;P2=0XA0;P0=buzz; //关闭继电器
			}
		}
		else //手动模式
		{
			led |=0x01;led &=0XFD;P2=0X80;P0=led; //打开L2,关闭L1
			if((move<threshold)&&(buzz_state==1)) //低于阈值且允许蜂鸣器打开
			{
				buzz|=0X40;P2=0XA0;P0=buzz; //打开蜂鸣器
			}
			else
			{
				buzz&=0Xbf;P2=0XA0;P0=buzz; //关闭蜂鸣器
			}
		}
		SMG_output();
		Dkey_scan();
	}
}

void Dkey_scan(void)
{
	static uchar keybyte=0;
	static uchar key;
	if(((P3&0X0F)!=0X0F)&&(keybyte==0))
	{
		delay5ms();
		if((P3&0X0F)!=0X0F)
		{
			keybyte=1;key=P3&0x0f;
		}
	}
	if((keybyte==1)&&((P3&0X0F)==0X0F))
	{
		if((P3&0X0F)==0X0F)
		{
			switch(key)
			{
				case 0x0e:
					if(work_mode==0)work_mode=1;
				  else work_mode=0;
					break;
				case 0x0d:
					if(work_mode==1) //手动模式下
					{
						if(buzz_state==1){buzz_state=0;P2=0XA0;P0=0X00;} //关闭蜂鸣器
						else {buzz_state=1;}//打开蜂鸣器使能
					}
					else  //自动模式下
					{
						if(SMG_mode==0)SMG_mode=1; //切换数码管状态
						else {SMG_mode=0;IIC_write(0xA0,0x00,threshold);} //存取EEPROM
					}
					break;
				case 0x0b:
					if(work_mode==1) //手动模式
					{
						buzz|=0X10;P2=0XA0;P0=buzz; //打开灌溉
					}
					else //自动模式下
					{
						threshold++; //阈值加1
						if(threshold>99)threshold=99; //范围
					}
					break;
				case 0x07:
					if(work_mode==1)//手动模式
					{
						buzz&=0XEF;P2=0XA0;P0=buzz; //关闭灌溉
					}
					else //自动模式下
					{
						threshold--; //阈值减1
						if(threshold<0)threshold=0; //范围
					}
					break;
			}
			keybyte=0;
		}
	}
}

void SMG_output(void)
{
	uchar i;
	for(i=0;i<8;i++)
	{
	P2=(P2&0X1F)|0Xc0;
	P0=(1<<i);
	P2=(P2&0X1F)|0Xe0;
	P0=tab[SMG[i]];
	Delay1ms();
	}
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void init(void)
{
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=(P2&0X1F)|0X80;
	P0=0Xff;
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}

void delay5ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

iic.c

#include "iic.h"

#define DELAY_TIME 40

void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);
	IIC_WaitAck();
	IIC_SendByte(num);
	IIC_WaitAck();	
	IIC_Stop();	
}	

uchar IIC_read(uchar hw_address,uchar reg_address)
{
	uchar num;
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);	
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(hw_address|0x01);
	IIC_WaitAck();
	num=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();	
	
	return num;
}

//
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
		IIC_Delay(DELAY_TIME);
		da <<= 1;
		if(SDA) da |= 1;
		SCL = 0;
		IIC_Delay(DELAY_TIME);
    }
    return da;    
}

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int

sbit SDA = P2^1;
sbit SCL = P2^0;

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
void IIC_write(uchar hw_address,uchar reg_address,uchar num);
uchar IIC_read(uchar hw_address,uchar reg_address);


#endif

ds1302.c

#include "ds1302.h"  									

uchar time[7]={0,30,8,0,0,0,0};

void ds1302_init(void)
{
	uchar i,j=0x80;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++)
	{
		Write_Ds1302_Byte(j,time[i]);
		j +=2;
	}
	Write_Ds1302_Byte(0x8e,0x80);
}

void get_time(void)
{
	uchar i,j=0x81;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++)
	{
		time[i]=Read_Ds1302_Byte(j);
		j +=2;
	}
	Write_Ds1302_Byte(0x8e,0x80);
}


//
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		IO = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(((dat/10)<<4)|(dat%10));
 	RST=0; 
}

//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(IO)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	IO=0;	_nop_();
	IO=1;	_nop_();
	return (((temp/16)*10)+(temp%16));			
}

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

#include <stc15f2k60s2.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit SCK = P1^7;		
sbit IO = P2^3;		
sbit RST = P1^3; 

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void get_time(void);
void ds1302_init(void);

#endif

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

月明Mo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值