第十五届蓝桥杯单片机模拟考试I

题目

 

 这道题输入四位数据,输入完成切换界面的时候写入EEProm里面去,输入四位数据,多余的按键不影响原来的输入,那我们就得限制输入的次数,输入四次就让后面的输入无效即可。写入EEprom里面的时间是初始输入时间,我们就对输入的次数进行判断,第一次输入的话,我们记录一下现在的时间保存起来,等到后面界面切换的时候写入eeprm里面去。

数据按照hex编码写入e2prom,我们就得对数据进行进制转换处理.写完用一个变量来记录写入值,用于下次输入数据的大小比较。

按键功能

S4界面切换,s5清除,其他的分别对应数字0~9,这种题目最好的做法是改底层,但是不修改底层也可以完成,只是代码会显得臃肿一些。

/*按键函数区域*/
void Key_Proc(){
	if(Key_Slow) return;
	Key_Slow = 1;
	
	Key_Val = Key_Read();
	Key_Down = Key_Val & (Key_Val ^ Key_Old);
	Key_Up = Key_Val & (Key_Val ^ Key_Old);
	Key_Old = Key_Val;
	
	
	if(Key_Down == 4){//按下按键S4,模式切换
		if(Seg_Mode == 1){//从输入界面转换到记录界面的时候触发eeprom的写入
			now_Val = Input_Val[0]*1000+Input_Val[1]*100+Input_Val[2]*10+Input_Val[3];//得到当前输入的四位数
			L4_bit = (now_Val > pre_Val);//L4根据题意是在记录界面才会点亮,所以我们在输入界面转换到记录界面的时候再对L4进行判断~~~~~
			EE_Val[0] = Time_record[0]/16*10+Time_record[0]%16;//DS1302是16进制的,改成10进制的写入eeprom~~~~~~~~~~~~~~~~~~~~~~~~~~~
			EE_Val[1] = Time_record[1]/16*10+Time_record[1]%16;
			EE_Val[2] = now_Val>>8;//得到高八位
			EE_Val[3] = now_Val & 0x00ff;//获取低八位
			EE_Write(EE_Val,0,4);
			pre_Val = now_Val;
		}
		if(++Seg_Mode == 3) Seg_Mode = 0;
		Input_Index = 4;//每次模式切换就重置输入的数据个数
		
	}
	if(Seg_Mode == 1){//其他按键都在输入界面有效
		if(Key_Down == 5){//在输入界面清除数据
					Input_Val[0] = 10;//数据清除完数码管熄灭
					Input_Val[1] = 10;
					Input_Val[2] = 10;
					Input_Val[3] = 10;
					Input_Index = 4 ;
		}
		if(Input_Index){//数据没有全部输入完,4,3,2,1输入四次
			switch(Key_Down){
				case 6://0
					Input_Index--;//能输入的数据个数减少一位
					Input_Val[3-Input_Index] = 0;//对应的数据位为0
				break;
				case 10://1
					Input_Index--;
					Input_Val[3-Input_Index] = 1;//对应的数据位为1
				break;
				case 14://2
					Input_Index--;
					Input_Val[3-Input_Index] = 2;//对应的数据位为2
				break;
				case 18://3
					Input_Index--;
					Input_Val[3-Input_Index] = 3;//对应的数据位为3
				break;
				case 9://4
					Input_Index--;
					Input_Val[3-Input_Index] = 4;//对应的数据位为4
				break;
				case 13://5
					Input_Index--;
					Input_Val[3-Input_Index] = 5;//对应的数据位为5
				break;
				case 17://6
					Input_Index--;
					Input_Val[3-Input_Index] = 6;//对应的数据位为6
				break;
				case 8://7
					Input_Index--;
					Input_Val[3-Input_Index] = 7;//对应的数据位为7
				break;
				case 12://8
					Input_Index--;
					Input_Val[3-Input_Index] = 8;//对应的数据位为8
				break;
				case 16://9
					Input_Index--;
					Input_Val[3-Input_Index] = 9;//对应的数据位为9
				break;
			}				
		}
	}
	
	
}

显示功能

 时间功能是正常的时间显示,输入界面得高位熄灭和最新输入的在右侧,之前的输入左移一位,这算个小难点,但是用索引对数组进行处理就行了,只有四位数据,我们直接对输入索引进行枚举就行了,记录界面在输入第一位的时候进行时间记录,把记录的时间显示出来即可。

/*数码管函数区域*/
void Seg_Proc(){
	if(Seg_Slow) return;
	Seg_Slow = 1;
	
	if(Input_Index == 3) Time_Read(Time_record);//第一次输入完成,记录输入时间
	
	switch(Seg_Mode){
		case 0://时间界面
			Time_Read(Time);//只在时间界面读取时间,可以优化程序运行~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			Seg_Buf[0] = Time[0]/16;
			Seg_Buf[1] = Time[0]%16;
			Seg_Buf[2] = 11;//-
			Seg_Buf[3] = Time[1]/16;
			Seg_Buf[4] = Time[1]%16;
			Seg_Buf[5] = 11;//-
			Seg_Buf[6] = Time[2]/16;
			Seg_Buf[7] = Time[2]%16;
		break;
		case 1://输入界面
			Seg_Buf[0] = 12;//C
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			if(Input_Index == 4){//没有输入	
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = 10;
				Seg_Buf[7] = 10;
			}
			else if(Input_Index == 3){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = 10;
				Seg_Buf[7] = Input_Val[0];
			}
			else if(Input_Index == 2){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = Input_Val[0];
				Seg_Buf[7] = Input_Val[1];
			}
			else if(Input_Index == 1){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = Input_Val[0];
				Seg_Buf[6] = Input_Val[1];
				Seg_Buf[7] = Input_Val[2];
			}
			else{
				Seg_Buf[4] = Input_Val[0];
				Seg_Buf[5] = Input_Val[1];
				Seg_Buf[6] = Input_Val[2];
				Seg_Buf[7] = Input_Val[3];
			}
		break;
		case 2://记录界面
			Seg_Buf[0] = 13;//E
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = Time_record[0]/16;
			Seg_Buf[4] = Time_record[0]%16;//时间
			Seg_Buf[5] = 11;//-
			Seg_Buf[6] = Time_record[1]/16;//分钟
			Seg_Buf[7] = Time_record[1]%16;
		break;
	}
	
}

Led功能 

L123常规界面指示灯

L4需要从E2prom里面读取上一次记录的数据来进行比较,但是我们可以取巧,直接定义一个变量来记录上一次的数据,这样就免去了e2prom的读取和进制转换的麻烦了。

L4的判断在按键功能里面

/*Led函数区域*/
void Led_Proc(){
	Led_Buf[0] = Seg_Mode==0?1:0;//时间界面点亮L1
	Led_Buf[1] = Seg_Mode==1?1:0;//输入界面点亮L2
	Led_Buf[2] = Seg_Mode==2?1:0;//记录界面点亮L3
	Led_Buf[3] = L4_bit;//如果本次记录的四位数大于上次点亮L4
}

 完整主函数

/*头文件区域*/
#include <STC15F2K60S2.H>
#include <Seg.h>
#include <Led.h>
#include <Init.h>
#include <Key.h>
#include <ds1302.h>
#include <iic.h>
/*参数变量区域*/
unsigned char Seg_Slow,Key_Slow;
unsigned char Key_Up,Key_Down,Key_Val,Key_Old;
unsigned char Seg_Pos;
unsigned char Seg_Mode;//0时间界面,1输入界面,2记录界面
//数组
unsigned char Seg_Buf[] = {10,10,10,10,10,10,10,10};
unsigned char Led_Buf[] = {0,0,0,0,0,0,0,0};
unsigned char Point[] = {0,0,0,0,0,0,0,0};
unsigned char Input_Val[4] = {10,10,10,10};
unsigned char Input_Index = 4;
unsigned char Time[3] = {0x23,0x09,0x59};
unsigned char Time_record[3] = {0x00,0x00,0x00};
unsigned char EE_Val[4] = {0x00,0x00,0x00,0x00};
unsigned char EE_Out[4] = {0x00,0x00,0x00,0x00};
//数据
unsigned int now_Val;//现在的输入值
unsigned int pre_Val = 10000;//之前的输入值,这样第一次输入值就不会点亮L4
bit L4_bit;//L4亮灭标志位 
/*按键函数区域*/
void Key_Proc(){
	if(Key_Slow) return;
	Key_Slow = 1;
	
	Key_Val = Key_Read();
	Key_Down = Key_Val & (Key_Val ^ Key_Old);
	Key_Up = Key_Val & (Key_Val ^ Key_Old);
	Key_Old = Key_Val;
	
	
	if(Key_Down == 4){//按下按键S4,模式切换
		if(Seg_Mode == 1){//从输入界面转换到记录界面的时候触发eeprom的写入
			now_Val = Input_Val[0]*1000+Input_Val[1]*100+Input_Val[2]*10+Input_Val[3];//得到当前输入的四位数
			L4_bit = (now_Val > pre_Val);//L4根据题意是在记录界面才会点亮,所以我们在输入界面转换到记录界面的时候再对L4进行判断~~~~~
			EE_Val[0] = Time_record[0]/16*10+Time_record[0]%16;//DS1302是16进制的,改成10进制的写入eeprom~~~~~~~~~~~~~~~~~~~~~~~~~~~
			EE_Val[1] = Time_record[1]/16*10+Time_record[1]%16;
			EE_Val[2] = now_Val>>8;
			EE_Val[3] = now_Val & 0x00ff;
			EE_Write(EE_Val,0,4);
			pre_Val = now_Val;
		}
		if(++Seg_Mode == 3) Seg_Mode = 0;
		Input_Index = 4;//每次模式切换就重置输入的数据个数
		
	}
	if(Seg_Mode == 1){//其他按键都在输入界面有效
		if(Key_Down == 5){//在输入界面清除数据
					Input_Val[0] = 10;//数据清除完数码管熄灭
					Input_Val[1] = 10;
					Input_Val[2] = 10;
					Input_Val[3] = 10;
					Input_Index = 4 ;
		}
		if(Input_Index){//数据没有全部输入完,4,3,2,1输入四次
			switch(Key_Down){
				case 6://0
					Input_Index--;//能输入的数据个数减少一位
					Input_Val[3-Input_Index] = 0;//对应的数据位为0
				break;
				case 10://1
					Input_Index--;
					Input_Val[3-Input_Index] = 1;//对应的数据位为1
				break;
				case 14://2
					Input_Index--;
					Input_Val[3-Input_Index] = 2;//对应的数据位为2
				break;
				case 18://3
					Input_Index--;
					Input_Val[3-Input_Index] = 3;//对应的数据位为3
				break;
				case 9://4
					Input_Index--;
					Input_Val[3-Input_Index] = 4;//对应的数据位为4
				break;
				case 13://5
					Input_Index--;
					Input_Val[3-Input_Index] = 5;//对应的数据位为5
				break;
				case 17://6
					Input_Index--;
					Input_Val[3-Input_Index] = 6;//对应的数据位为6
				break;
				case 8://7
					Input_Index--;
					Input_Val[3-Input_Index] = 7;//对应的数据位为7
				break;
				case 12://8
					Input_Index--;
					Input_Val[3-Input_Index] = 8;//对应的数据位为8
				break;
				case 16://9
					Input_Index--;
					Input_Val[3-Input_Index] = 9;//对应的数据位为9
				break;
			}				
		}
	}
	
	
}
/*数码管函数区域*/
void Seg_Proc(){
	if(Seg_Slow) return;
	Seg_Slow = 1;
	
	if(Input_Index == 3) Time_Read(Time_record);//第一次输入完成,记录输入时间
	
	switch(Seg_Mode){
		case 0://时间界面
			Time_Read(Time);//只在时间界面读取时间,可以优化程序运行~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			Seg_Buf[0] = Time[0]/16;
			Seg_Buf[1] = Time[0]%16;
			Seg_Buf[2] = 11;//-
			Seg_Buf[3] = Time[1]/16;
			Seg_Buf[4] = Time[1]%16;
			Seg_Buf[5] = 11;//-
			Seg_Buf[6] = Time[2]/16;
			Seg_Buf[7] = Time[2]%16;
		break;
		case 1://输入界面
			Seg_Buf[0] = 12;//C
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			if(Input_Index == 4){//没有输入	
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = 10;
				Seg_Buf[7] = 10;
			}
			else if(Input_Index == 3){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = 10;
				Seg_Buf[7] = Input_Val[0];
			}
			else if(Input_Index == 2){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = 10;
				Seg_Buf[6] = Input_Val[0];
				Seg_Buf[7] = Input_Val[1];
			}
			else if(Input_Index == 1){
				Seg_Buf[4] = 10;
				Seg_Buf[5] = Input_Val[0];
				Seg_Buf[6] = Input_Val[1];
				Seg_Buf[7] = Input_Val[2];
			}
			else{
				Seg_Buf[4] = Input_Val[0];
				Seg_Buf[5] = Input_Val[1];
				Seg_Buf[6] = Input_Val[2];
				Seg_Buf[7] = Input_Val[3];
			}
		break;
		case 2://记录界面
			Seg_Buf[0] = 13;//E
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = Time_record[0]/16;
			Seg_Buf[4] = Time_record[0]%16;//时间
			Seg_Buf[5] = 11;//-
			Seg_Buf[6] = Time_record[1]/16;//分钟
			Seg_Buf[7] = Time_record[1]%16;
		break;
	}
	
}
/*Led函数区域*/
void Led_Proc(){
	Led_Buf[0] = Seg_Mode==0?1:0;//时间界面点亮L1
	Led_Buf[1] = Seg_Mode==1?1:0;//输入界面点亮L2
	Led_Buf[2] = Seg_Mode==2?1:0;//记录界面点亮L3
	Led_Buf[3] = L4_bit;//如果本次记录的四位数大于上次点亮L4
}
/*定时器0初始化函数区域*/
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
/*定时器0中断服务函数区域*/
void Timer0_Service() interrupt 1
{
	if(++Seg_Slow == 50) Seg_Slow = 0;
	if(++Key_Slow == 50) Key_Slow = 0;
	
	if(++Seg_Pos == 8) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Point[Seg_Pos]);
	Led_Disp(Seg_Pos,Led_Buf[Seg_Pos]);
	
}

/*主函数区域*/
void main(){
	Sys_Init();
	Timer0_Init();
	Time_Write(Time);//上电写入时间
	while(1){
		Key_Proc();
		Led_Proc();
		Seg_Proc();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值