题目
这道题输入四位数据,输入完成切换界面的时候写入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();
}
}