蓝桥杯---第三届赛题

为什么要从第三届开始刷题呢?因为前面两届的题与最新的考试有些脱轨,故而不再练习。

前天已经刷完了赛题,实现大多数的功能。本以为很成功,但是呢,由于疏忽,没有从整体上去理解赛题,,以为只是点点灯,显示数码管之类的简单操作。但是,它柔和了PCF8591和AD转换器的知识,还有两个重要的知识IIC通信和中断。最后,就是怎么改驱动。

第三届 自动售水机
<1>: 数码管,LED,独立按键,继电器
<2>:IIC通信( AD转换器即PCF8591)
<3>:中断与定时器

第一部分:大多为必考内容,平时可以将其写成模块化。

 #include<stc15f2k60s2.h>
		
		#define uchar unsigned char 
		#define uint  unsigned int
		
		uchar code tab[]={0xc0,0xf9,0xa0,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
		uchar yi,er,san,si,wu,liu,qi,ba;
		bit S7=0,S6=0,S5=0,S4=0;
		uchar num=0;
		uchar key=0;
		
		void display1(uchar yi,uchar er);
		void display2(uchar san,uchar si);
		void display3(uchar wu,uchar liu);
		void display4(uchar qi,uchar ba);
		void allinit();
		void  delayms(int ms);
		void keyscan();
		
		void main(void)
		{
			allinit();
			yi=0;er=8;san=10;si=3;wu=0;liu=10;qi=0;ba=0;
			while(1)
			{
				
				display1(yi,er);
				display2(san,si);
				display3(wu,liu);
				display4(qi,ba);
			}
		}
		void keyscan()
		{
			if(P30==0)
			{
				delayms(5);
				if(P30==0)
				{
					S7=1;
				}
				while(!P30);//上升沿检测
			}
			
			else if(P31==0)
			{
				delayms(5);
				if(P31==0)
				{
					S6=1;
				}
				while(!P31);
			}
			
				else if(P32==0)
			{
				delayms(5);
				if(P32==0)
				{
					S5=1;
				}
				while(!P32);
			}
				else if(P33==0)
			{
				delayms(5);
				if(P33==0)
				{
					S4=1;
				}
				while(!P33);
			}
		}
		
		
		void allinit()
		{
			P2=0XA0;
			P0=0x00;
			
			P2=0X80;
			P0=0XFF;
			
			P2=0XC0;
			P0=0XFF;
			P2=0XFF;
			P0=0XFF;
		}
			
		void display1(uchar yi,uchar er)
		{
			P2=0XC0;
			P0=0X01;
			P2=0XFF;
			P0=tab[yi];
			delayms(5);
			
			P2=0XC0;
			P0=0X01;
			P2=0XFF;
			P0=tab[er];
		}
		
		void display2(uchar san,uchar si)
		{
			P2=0XC0;
			P0=0X04;
			P2=0XFF;
			P0=tab[san];
			delayms(5);
			
			P2=0XC0;
			P0=0X08;
			P2=0XFF;
			P0=tab[si];
			delayms(5);
		}	
		void display3(uchar wu,uchar liu)
		{
			P2=0XC0;
			P0=0X10;
			P2=0XFF;
			P0=tab[wu];
			delayms(5);
			
			P2=0XC0;
			P0=0X20;
			P2=0XFF;
			P0=tab[liu];
			delayms(5);
		}	
		void display4(uchar qi,uchar ba)
		{
			P2=0XC0;
			P0=0X40;
			P2=0XFF;
			P0=tab[qi];
			delayms(5);
			
			P2=0XC0;
			P0=0X80;
			P2=0XFF;
			P0=tab[ba];
			delayms(5);
		}	
		
		void  delayms(int ms)
		{
			int i,j;
			for(i=ms;i>0;i--)
				for(j=845;j>0;j--);
		}

第二部分:IIC通信只联系到PCF8591的部分,将驱动进行稍微的更改。其实只是涉及到读的要求,只要加上一个读的函数即可。

uchar  IIC_read(uchar add)
{
	uchar temp;
	
	IIC_Start();//开始信号
	IIC_SendByte(0x90);//PCF8591
	IIC_WaitAck();//等待响应
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();//开始信号
	IIC_SendByte(0x91);//PCF8591
	IIC_WaitAck();//等待响应
	temp=IIC_RecByte();//读出的数据
	IIC_Stop();
	
	return temp;
}

第三部分:中断与定时器。其实并不难,只需要在以前的基础上,根据赛题的要求,进行更改。

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


void timer0() interrupt  1
{
	tt++;
	if(tt==20)//判断是否满100毫秒
	{
		tt=0;
		ML_10=ML_10+1;//满10毫升加1 每一百毫秒加10毫升
		wu=ML_10/1000;liu=ML_10%1000/100;qi=ML_10%100/10;ba=ML_10%10;//在数码管显示值
				if(ML_10>9999) 
				{
					ET0=0;
					EA=0;
					
					P2=0xa0;
					P0=0X00;
					
					money=ML_10*0.5;
							wu=money/1000;liu=money%1000/100;qi=money%100/10;ba=money%10;
				ML_10=0;
				}
	}
	
}

到这里赛题的功能已经实现了。

经验总结:

1.要有一个整体的概念,每个模块之间都有一定的联系。

2.学会根据赛题改驱动。

3.注意些细节的问题,举个栗子:赛题要求出水速度为:100毫升/秒,而数码管显示要求保留两位小数,此时,就不能再一100毫升/秒的想法写程序,需要转化一下。这一步,在定时器中实现的。具体的做法:精确定时为5毫秒,在计数器中记20下,就是100毫秒,其中是10毫升,(即10毫升/100毫秒)。

4.遇到了一个问题,就是怎么判定光敏电阻是否到了1.25v。当时,查了手册,想了很久。后来,我知道了。单片机只认二进制,就需要转化一下。有一个算式:1.25/5*255=63.74,看做是64。这样问题就解决了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值