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

链接:https://pan.baidu.com/s/1ab56vyanN9NLMR3jvzaWCg
提取码:85go
复制这段内容后打开百度网盘手机App,操作更方便哦
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

main.c

#include "main.h"
extern unsigned int key_number;//按键键值
extern unsigned char key_flag;//按键按下标志
extern unsigned char hour,minute;//DS1302的小时和分钟
unsigned char shidu;//湿度
unsigned int shidu_temp;//湿度转换后的
unsigned char yuzhi=50;//阈值
unsigned char code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位码
unsigned char code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0xc8,0x8c,0xc1,0xbf,0xff,0x7f,0x00};//段码

unsigned char duan_buff[]={0,0,0,0,0,0,0,0};

 unsigned int key_s6_flag=0;//按键s6的专属标志


unsigned char mode=1;//模式定义
void main(void)
{
	Timer1Init();
	Timer0Init();
	DS1302_init(0x08,0x30);
	close();
	while(1)
	{

//		if(key_s6_flag==0)
//		{
//			duan_buff_change(key_number);
//					led_segment_display();
//		}
//		else
//		{
//				if(key_number==8)
//				{
//					yuzhi+=1;
//					duan_buff_change(yuzhi);
//					led_segment_display();
//					key_flag=0;
//					key_number=999;
//				}
//				if(key_number==12)
//				{
//					yuzhi-=1;
//					duan_buff_change(yuzhi);
//					led_segment_display();
//					key_flag=0;
//					key_number=9999;
//				}
//			}
//		

		
/********************************************************
对于自动状态
********************************************************/		
				if(mode==1)
				{
							shidu=PCF8591(0x03);
							shidu_temp=((shidu*1.0)/255*1000+0.5)/10;
							DS1302_read();
					
//					if(key_number==4)
//					{
//						if(key_s6_flag==1)
//						{
//							key_s6_flag=0;
//						}
//						key_s6_flag=1;
//						
//					}
//									
					
					if(key_s6_flag==0)
					{
						duan_buff_change2(shidu_temp%10,shidu_temp/10%10,22,minute%16,minute/16,21,hour%16,hour/16);
					}
					else
					{
		
/********************************************************
对于自动状态下的阈值调整
********************************************************/		
											if(key_number==8)
											{
												yuzhi+=1;
												duan_buff_change(yuzhi);
												eeprom_write(0x00,yuzhi);
												led_segment_display();
												key_flag=0;
												key_number=999;
											}
											if(key_number==12)
											{
												yuzhi-=1;
												eeprom_write(0x00,yuzhi);
												duan_buff_change(yuzhi);
												led_segment_display();
												key_flag=0;
												key_number=9999;
											}
												duan_buff_change2(yuzhi%10,yuzhi/10%10,22,22,22,22,21,21);
					}
								led_segment_display();

/********************************************************
对于自动状态下的自动状态灌溉
********************************************************/							

								if(shidu_temp<yuzhi)
								{
									Y5;
									P0=0X10;
									Y4;
									P0=0xfe;				
									P2&=0X1F;

								}
								else
								{
									Y5;
									P0=0X00;
									Y4;
									P0=0xff;				
									P2&=0X1F;

								}	

								
				}	
								
			
		
		
		
		
		
		
/********************************************************
对于手动状态
********************************************************/		
		
		
		if(mode==0)
		{
				shidu=PCF8591(0x03);//ad采样
				shidu_temp=((shidu*1.0)/255*1000+0.5)/10;//转换为湿度值(0-255)对应(0-100)的湿度
				DS1302_read();//读DS1302芯片
				duan_buff_change2(shidu_temp%10,shidu_temp/10%10,22,minute%16,minute/16,21,hour%16,hour/16);//段码缓存
				led_segment_display();
			
			
/********************************************************
对于手动状态的s6按键的蜂鸣器控制
********************************************************/
			if((key_s6_flag==1)||(shidu_temp<yuzhi))
			{
					Y5;
					P0=0X40;
					P2&=0X1F;		
					key_flag=0;
			}
			else
			{
					Y5;
					P0=0X00;
					P2&=0X1F;
				key_flag=0;
			}
/********************************************************
对于手动状态的s5按键的继电器控制
********************************************************/			
			if(key_number==8)
			{
				
				Y5;
				P0=0X10;
				Y4;
				P0=0xfd;
				P2&=0X1F;
				key_flag=0;
				
			}
/********************************************************
对于手动状态的s4按键的继电器控制
********************************************************/	
			if(key_number==12)
			{
				Y5;
				P0=0X00;
				Y4;
				P0=0xff;				
				P2&=0X1F;
				key_flag=0;
			}		
		}
		

	}
}

/********************************************************
数码管显示函数
********************************************************/

void led_segment_display()
{
	unsigned int num=0;
	for(num=0;num<8;num++)
	{
		Y6;
		P0=wei[7-num];
		P2&=0X1F;
		Y7;
		P0=duan[duan_buff[num]];	
		Delay1ms();
		P2&=0X1F;
		P0=0XFF;		
	}
	num=0;
}
/********************************************************
数码管段码的缓存区
处理数据方式2
********************************************************/
void duan_buff_change(unsigned int number)
{
	duan_buff[0]=number%10;
	duan_buff[1]=number/10%10;
	duan_buff[2]=number/100%10;
	duan_buff[3]=number/1000%10;
	duan_buff[4]=number/10000%10;
	duan_buff[5]=number/100000%10;
	duan_buff[6]=number/1000000%10;
	duan_buff[7]=number/10000000%10;	
}
/********************************************************
数码管段码的缓存区
处理数据方式2
********************************************************/
void duan_buff_change2(unsigned char d0,d1,d2,d3,d4,d5,d6,d7)
{
	duan_buff[0]=d0;
	duan_buff[1]=d1;
	duan_buff[2]=d2;
	duan_buff[3]=d3;
	duan_buff[4]=d4;
	duan_buff[5]=d5;
	duan_buff[6]=d6;
	duan_buff[7]=d7;
}







/********************************************************
定时器中断初始化
********************************************************/


void Timer1Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x00;		//设置定时初值
	TH1 = 0x28;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	EA=1;
	ET1=1;
}
/********************************************************
检测矩阵按键一个按键按两次,但是两次的功能不同
定时器中断服务函数
********************************************************/
void time1(void) interrupt 3
{
/********************************************************
对于按键s7的检测
	注意消去key_number的值,避免影响下一次判断,因为这个key_number会一直存储着,
	在下一次就又会进入这个判断程序,即使你并没有按下按键
********************************************************/
				if(key_number==0)
			{
				if(mode==0)
				{
					mode=1;
					key_number=9999;
					key_flag=0;
				}
				else
				{
					mode=0;
					key_number=9999;
					key_flag=0;
				}
			}

/********************************************************
对于按键s6的检测
注意消去key_number的值,避免影响下一次判断,因为这个key_number会一直存储着,
在下一次就又会进入这个判断程序,即使你并没有按下按键
********************************************************/		
								if(key_number==4)
					{
						if(key_s6_flag==1)
						{
							key_number=999;
							key_s6_flag=0;
										key_flag=0;
						}
						else
						{	
							key_number=999;
							key_s6_flag=1;
										key_flag=0;
						}
							
					}
							
								
}

main.h

#ifndef _MAIN_H
#define _MAIN_H


#include "common.h"

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

#include "inter.h"


void duan_buff_change(unsigned int number);
void led_segment_display();
void duan_buff_change2(unsigned char d0,d1,d2,d3,d4,d5,d6,d7);

void Timer1Init(void);
void time1(void);


#endif

common.c

#include "common.h"


/********************************************************
关闭外设
********************************************************/	
void close(void)
{
	Y4;P0=0XFF;
	P2&=0X1F;
	Y5;
	P0=0X00;
	P2&=0X1F;	
}


/********************************************************
延时函数
********************************************************/	

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

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



common.h

#ifndef _COMMON_H
#define _COMMON_H


#include "STC15F2K60S2.H"
#include "intrins.h"



/********************************************************
锁存器
********************************************************/
#define Y4 P2=(P2&0X1F)|0X80
#define Y5 P2=(P2&0X1F)|0Xa0
#define Y6 P2=(P2&0X1F)|0Xc0
#define Y7 P2=(P2&0X1F)|0Xe0

void close(void);




void Delay1ms()	;



#endif

iic.c

#include "iic.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}    


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */


//总线启动条件
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

//应答位控制
void IIC_Ack(bit ackbit)
{
	if(ackbit) 
	{	
		SDA = 0;
	}
	else 
	{
		SDA = 1;
	}
	somenop;
	SCL = 1;
	somenop;
	SCL = 0;
	SDA = 1; 
	somenop;
}

//等待应答
bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}

/********************************************************
eeprom写入数据
********************************************************/	
void eeprom_write(unsigned char address,unsigned char date)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(address);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	IIC_Stop();
	
}
/********************************************************
eeprom读出数据
********************************************************/	
unsigned char eeprom_read(unsigned char address)
{
	unsigned char date;
		IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(address);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	date=IIC_RecByte();
	IIC_Ack(0);
	IIC_Stop();
	return date;
	
}
/********************************************************
电位器
********************************************************/	
unsigned char PCF8591(unsigned char address)
{
	unsigned char date;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(address);
	IIC_WaitAck();
	IIC_Stop();

	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	date=IIC_RecByte();
	IIC_Ack(0);
	IIC_Stop();
	return date;
	
}

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "common.h"


unsigned char eeprom_read(unsigned char address);
void eeprom_write(unsigned char address,unsigned char date);
unsigned char PCF8591(unsigned char address);








#endif

DS1302.C



#include "ds1302.h"

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

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

void Write_Ds1302( unsigned char address,unsigned char dat )     
{
 	RST=0;
	_nop_();
 	SCK=0;
	_nop_();
 	RST=1;	
   	_nop_();  
 	Write_Ds1302_Byte(address);	
 	Write_Ds1302_Byte(dat);		
 	RST=0; 
}

unsigned char Read_Ds1302 ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;
	_nop_();
 	SCK=0;
	_nop_();
 	RST=1;
	_nop_();
 	Write_Ds1302_Byte(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;
	_nop_();
 	RST=0;
	SCK=0;
	_nop_();
	SCK=1;
	_nop_();
	SDA=0;
	_nop_();
	SDA=1;
	_nop_();
	return (temp);			
}
/********************************************************
DS1302初始化时间
********************************************************/	
void DS1302_init(unsigned char hour,unsigned char minute)
{
	Write_Ds1302(0x84,hour);
	Write_Ds1302(0x82,minute);
}


unsigned char hour,minute;

/********************************************************
读DS1302
********************************************************/
void DS1302_read(void)
{
	hour=Read_Ds1302(0x85);
	minute=Read_Ds1302(0x83);
}

DS1302.H

#ifndef __DS1302_H
#define __DS1302_H

#include "common.h"

void DS1302_init(unsigned char hour,unsigned char minute);
void DS1302_read(void);




#endif

inter.c

#include "inter.h"
unsigned int key_number=9999;//按键键值
unsigned char key_flag=0;//按键按下标志

/********************************************************
初始化定时器中断0
********************************************************/
void Timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}





/********************************************************
定时器0中断服务函数
********************************************************/
void time0(void) interrupt 1
{
		key_scan();
}

/********************************************************
矩阵键盘扫描
********************************************************/
void key_scan(void)
{
	unsigned char key_x=0;
	unsigned char key_y=0;
	if(key_flag==0)
	{
		P3=0x0f;P42=0;P44=0;
		if(!P30|!P31|!P32|!P33)
		{
			if(P30==0) key_y=1;
			if(P31==0) key_y=2;
			if(P32==0) key_y=3;
			if(P33==0) key_y=4;			
		}
		P3=0XF0;P42=1;P44=1;
		if(!P34|!P35|!P42|!P44)		
		{
			if(P34==0) key_x=4;
			if(P35==0) key_x=3;
			if(P42==0) key_x=2;
			if(P44==0) key_x=1;			
		}
		if(key_x&&key_y)
		{
			key_number=4*key_y+key_x-5;
			key_flag=1;
			while(!P34|!P35|!P42|!P44);
		}
		else
			key_flag=0;
	}
}

inter.h

#ifndef _INTER_H
#define _INTER_H


#include "common.h"


void Timer0Init(void);
void time0(void) ;
void key_scan(void);

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想要不掉毛的程序羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值