当前位置: 首页> 教育> 大学 > 南充房产网二手房_比地招标网官网_网站推广策划书范文_搜索引擎排行榜

南充房产网二手房_比地招标网官网_网站推广策划书范文_搜索引擎排行榜

时间:2025/7/13 16:37:53来源:https://blog.csdn.net/2301_79437046/article/details/146053527 浏览次数:1次
南充房产网二手房_比地招标网官网_网站推广策划书范文_搜索引擎排行榜

第十五届4T模拟赛一可以说是这几届以来的4T模拟赛题目最难、最有含金量的一届了,难度可以和十三届之前的省赛媲美了,题目中挖的坑很多,加上4T评分的连坐机制,得奖还是不容易的。自测建议用时:2个半小时(从头敲)。

三个难点:

  • 矩阵键盘模拟数值输入
  • 输入数值时记录时间
  • EEPROM写入特定格式的数据

附件:第十五届4T模拟赛一
在这里插入图片描述
在这里插入图片描述

一、题目分析

在这里插入图片描述
首先是第一个难点,矩阵键盘模拟数值输入,而且输入一个数值,先前输入的数值向左移动一位,这个就很烧脑了。
在这里插入图片描述
记录页面埋着一个最大的坑。如果你看完题目后和我一样认为记录的时间是从页面切换到记录页面的时间的话,就掉进出题人设计好的陷阱了,它显示的是输入四位数据的起始时间,也就是用户进入输入页面后第一次按下键盘时的时间
在这里插入图片描述
写入EEPROM的数据是有要求的,简单理解就是写入EEPROM的数据是十六进制的,要提前进行进制转换。

分析完题目后,就要开始考虑怎么逐步实现程序了,肯定是要从简单的入手
时间显示页面->记录页面(因为记录页面是和按键相关的,所以要先写按键转换输入数值,再写数码管怎么显示输入数值的过程)->记录页面->Led->EEPROM

二、数码管模块

1.时间页面

在这里插入图片描述

老样子,定义SegMode控制页面流转,页面1很简单,代码如下:

/*变量声明区*/
idata u8 SegPos;
idata u8 SegMode;//页面显示模式pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};
pdata u8 ucRtc[3] = {0x23,0x59,0x50};//时间存放数组
void SegProc()
{unsigned char i;switch(SegMode){case 0:SegBuf[2] = SegBuf[5] = 11;//-for(i = 0; i < 3; i++){SegBuf[3*i] = ucRtc[i] / 16;SegBuf[3*i+1] = ucRtc[i] % 16;}break;}
}

2.输入页面

在这里插入图片描述
输入页面和按键息息相关,先实现按键转换数值。
在这里插入图片描述

S6、S10、S14、S18、S9、S13、S17、S8、S12、S16对应数字0~9。

S6、S10、S14、S18对应0~3,不难看出S6、S10、S14、S18是公差为4的等差数列,,转换后的数值刚好是公差为1的等差数列。所以可以将每个按键的值减去6再除以4得到对应的数值。

(6-6)/4 = 0
(10-6)/4 = 1
(14-6)/4 = 2
(18-6)/4 = 3

同样的,S9、S13、S17也可以通过以下操作得到对应的数值:

第一步
(9-5)/4=1
(13-5)/4=2
(17-5)/4=3
第二步
1+3 = 4
2+3 = 5
3+3 = 6

S8、S12、S16

第一步
(8-8)/4=0
(12-8)/4=1
(16-8)/4=2
第二步
0+7=7
1+7=8
2+7=9
pdata u8 Input[4];//数据存放数组
idata u8 InputIndex;//数组的索引
void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;switch(KeyDown){case 6:case 10:case 14:case 18:Input[InputIndex++] = (KeyDown - 6) / 4;break;case 9:case 13:case 17:Input[InputIndex++] = (KeyDown - 5) / 4 + 3;break;case 8:case 12:case 16:Input[InputIndex++] = (KeyDown - 8) / 4 + 7;break;}
}

由于S6、S10、S14、S18、S9、S13、S17、S8、S12、S16只在输入页面有效,并且四位数据输入完成后,再按以上按键对显示页面没有影响,因此要加前置条件。

前置条件不能加在switch内的原因:switch内只能存在casebreak,不能在switch内出现if-else语句。

void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;if(SegMode == 1){if(InputIndex < 4){switch(KeyDown){case 6:case 10:case 14:case 18:Input[InputIndex++] = (KeyDown - 6) / 4;break;case 9:case 13:case 17:Input[InputIndex++] = (KeyDown - 5) / 4 + 3;break;case 8:case 12:case 16:Input[InputIndex++] = (KeyDown - 8) / 4 + 7;break;}}

数码管显示:
由于数码管的显示是和输入数据的个数息息相关的,所以首先考虑使用for循环并且循环条件和数据个数有关,然后慢慢想可以想到下面的这个for循环。

void SegProc()
{unsigned char i;switch(SegMode){case 1:SegBuf[0] = 12;for(i = 0; i < InputIndex; i++)SegBuf[7-i] = Input[InputIndex-i-1];break;}
}

3.记录页面

在这里插入图片描述
当第一次输入数值时,记录当时的时间。
第一次输入数值,也就是数据存放数组的索引值为1

pdata u8 ucRtc_record[2];//记录时间void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;if(SegMode == 1){if(InputIndex < 4){switch(KeyDown){//...}if(InputIndex == 1)//索引值为1时GetucRtc(ucRtc_record);//记录时间}}
}void SegProc()
{unsigned char i;switch(SegMode){case 2:SegBuf[0] = 13;SegBuf[1] = 10;SegBuf[2] = 10;SegBuf[3] = ucRtc_record[0] / 16;SegBuf[4] = ucRtc_record[0] % 16;SegBuf[5] = 11;SegBuf[6] = ucRtc_record[1] / 16;SegBuf[7] = ucRtc_record[1] % 16;	break;}
}

4.数码管完整代码

void SegProc()
{unsigned char i;switch(SegMode){case 0:SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){SegBuf[3*i] = ucRtc[i] / 16;SegBuf[3*i+1] = ucRtc[i] % 16;}break;case 1:SegBuf[0] = 12;for(i = 0; i < InputIndex; i++){SegBuf[7-i] = Input[InputIndex-i-1];}break;case 2:SegBuf[0] = 13;SegBuf[1] = 10;SegBuf[2] = 10;SegBuf[3] = ucRtc_record[0] / 16;SegBuf[4] = ucRtc_record[0] % 16;SegBuf[5] = 11;SegBuf[6] = ucRtc_record[1] / 16;SegBuf[7] = ucRtc_record[1] % 16;	break;}
}

三、按键模块

在这里插入图片描述

void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;if(SegMode == 1){if(InputIndex < 4){switch(KeyDown){case 6:case 10:case 14:case 18:Input[InputIndex++] = (KeyDown - 6) / 4;break;case 9:case 13:case 17:Input[InputIndex++] = (KeyDown - 5) / 4 + 3;break;case 8:case 12:case 16:Input[InputIndex++] = (KeyDown - 8) / 4 + 7;break;}if(InputIndex == 1)GetucRtc(ucRtc_record);}//清空输入的数据if(KeyDown == 5){InputIndex = 0;Input[0] = Input[1] = Input[2] = Input[3] = 0;SegBuf[4] = SegBuf[5] = SegBuf[6] = SegBuf[7] = 10;}}if(KeyDown == 4){SegMode++;//第一次进入输入页面,清空所有数据if(SegMode == 1){InputIndex = 0;Input[0] = Input[1] = Input[2] = Input[3] = 0;SegBuf[1] = 10;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = 10;SegBuf[6] = 10;SegBuf[7] = 10;}else if(SegMode == 3)SegMode = 0;}
}

四、EEPROM模块

在这里插入图片描述
也就是说,进入页面二的时候,将记录的时间数据、数据写入EEPROM的内部地址0~4,并且以十六进制的格式写入,所以写入EEPROM前要先进行进制转换。

/*变量声明*/pdata u8 EEPROM[4];idata u16 InputDat;//输入的数值转换成十进制
idata u16 InputOld = 9999;//防止第一次输入时标志位使能,第一次默认失效idata bit LedFlag;
void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;if(SegMode == 1){//...}if(KeyDown == 4){SegMode++;if(SegMode == 1){//...}//EEPROMelse if(SegMode == 2){InputDat = Input[0] * 1000 + Input[1] * 100 + Input[2] * 10 + Input[3];EEPROM[0] = (ucRtc_record[0] / 16) * 10 + ucRtc_record[0] % 16;EEPROM[1] = (ucRtc_record[1] / 16) * 10 + ucRtc_record[1] % 16;EEPROM[2] = InputDat >> 8;EEPROM[3] = InputDat & 0x00ff;eeprom_write(EEPROM,0,4);LedFlag = (InputDat > InputOld);//LED4使能标志位InputOld = InputDat;}else if(SegMode == 3)SegMode = 0;}
}

这边解释一下EEPROM[2] = InputDat >> 8;
EEPROM[3] = InputDat & 0x00ff;,由于InputDat 是将存放输入数据的数组转换成十进制,十进制转换成十六进制时,只需要将十进制转换成二进制,每四位二进制对应一位十六进制即可。

例如:InputDat的值为1025
1025的二进制:0000 0100 0000 00010000 0100 0000 0001的高八位提取出来:
0000 0100 0000 0001 >> 8 = 0000 01000000 0100 0000 0001的低八位提取出来:
0000 0100 0000 0001 & 0000 0000 1111 1111
= 0000 0001
也就是0000 0100 0000 0001 & 0x00ff = 0000 0001

五、Led模块

在这里插入图片描述

void LedProc()
{unsigned char i;for(i = 0; i < 3; i++)ucLed[i] = (i == SegMode);ucLed[3] = LedFlag;LedDisp(ucLed);
}

六、完整代码

#include <STC15F2K60S2.H>
#include "Init.h"
#include "LED.h"
#include "Key.h"
#include "Seg.h"
#include "ds1302.h"
#include "iic.h"/* 变量声明区 */
unsigned char Key_Slow;                                    //按键减速变量 10ms 
unsigned char Key_Val, Key_Down, Key_Up, Key_Old;          //按键检测四件套
unsigned int Seg_Slow; //数码管减速变量 500ms
unsigned char Seg_Buf[] = {10,10,10,10,10,10,10,10,10,10}; //数码管缓存数组
unsigned char Seg_Pos;                                     //数码管缓存数组专用索引
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};            //数码管小数点使能数组
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};                //LED显示数据存放数组
unsigned char ucRtc[3] = {0x23,0x59,0x55};				   //存放时间
unsigned char Seg_Mode;                                    //页面显示
unsigned char Input[3];						               //存放记录的时、分
unsigned char Input_Dat[4];								   //存放输入的四位数据
unsigned char Input_Dat_Index;                             //存放输入的四位数据索引
unsigned int Dat_New;									   //输入的四位数据转换十进制
unsigned int Dat_Old = 9999;					           //输入四位数据上次的值
unsigned char EEPROM_Dat[4];                               //EEPROM的数据
bit LED4;                                                  //Led使能位/* 按键处理函数 */
void Key_Proc()
{unsigned char i;if(Key_Slow) return;Key_Slow = 1; //按键减速Key_Val = Key();Key_Down = Key_Val & ~Key_Old;	 Key_Up = ~Key_Val & Key_Old;Key_Old = Key_Val;if(Seg_Mode == 1)//处于输入页面{if(Key_Down == 5){for(i = 0; i < 4; i++)Input_Dat[i] = 10;Input_Dat_Index = 0;}if(Input_Dat_Index == 1)DS1302_Read(Input);if(Input_Dat_Index < 4){switch(Key_Down){case 6:case 10:case 14:case 18:Input_Dat[Input_Dat_Index] = (Key_Down - 6) / 4;Input_Dat_Index++;break;case 9:case 13:case 17:Input_Dat[Input_Dat_Index] = (Key_Down / 4) + 2;Input_Dat_Index++;break;case 8:case 12:case 16:Input_Dat[Input_Dat_Index] = (Key_Down / 4) + 5;Input_Dat_Index++;break;}}}if(Key_Down == 4){if(++Seg_Mode == 3)Seg_Mode = 0;if(Seg_Mode == 2){Dat_New = Input_Dat[0] * 1000 + Input_Dat[1] * 100 + Input_Dat[2] * 10 + Input_Dat[3];EEPROM_Dat[0] = (Input[0] / 16) * 10 + Input[0] % 16;EEPROM_Dat[1] = (Input[1] / 16) * 10 + Input[1] % 16;EEPROM_Dat[2] = Dat_New >> 8;EEPROM_Dat[3] = Dat_New & 0x00ff;EEPROM_Write(EEPROM_Dat,0,4);LED4 = (Dat_New > Dat_Old);Dat_Old = Dat_New;}for(i = 0; i < 4; i++)Input_Dat[i] = 10;Input_Dat_Index = 0;}
}/* 信息处理函数 */
void Seg_Proc()
{unsigned char i;if(Seg_Slow) return;Seg_Slow = 1; //数码管减速DS1302_Read(ucRtc);switch(Seg_Mode){case 0:Seg_Buf[2] = Seg_Buf[5] = 11;for(i = 0; i < 3; i++){Seg_Buf[3*i] = ucRtc[i] / 16;Seg_Buf[3*i+1] = ucRtc[i] % 16;}break;case 1:Seg_Buf[0] = 12;for(i = 1; i < 4; i++) Seg_Buf[i] = 10;if(Input_Dat_Index == 0)for(i = 4; i < 8; i++) Seg_Buf[i] = 10;elsefor(i = 0; i < Input_Dat_Index; i++){Seg_Buf[7 - i] = Input_Dat[Input_Dat_Index - i - 1];}break;case 2:Seg_Buf[0] = 13;Seg_Buf[3] = Input[0] / 16;Seg_Buf[4] = Input[0] % 16;Seg_Buf[5] = 11;Seg_Buf[6] = Input[1] / 16;Seg_Buf[7] = Input[1] % 16;break;}
}/* 其他显示函数 */
void Led_Proc()
{unsigned char i;for(i = 0; i < 3; i++)ucLed[i] = (i == Seg_Mode);ucLed[3] = LED4;
}/* 定时器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_Server() interrupt 1
{if(++Key_Slow == 10) Key_Slow = 0; //按键延迟if(++Seg_Slow == 100) Seg_Slow = 0; //数码管延迟if(++Seg_Pos == 8) Seg_Pos = 0;	   //数码管显示Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);LED_Disp(Seg_Pos,ucLed[Seg_Pos]);
}void main()
{DS1302_Write(ucRtc);Init();Timer0_Init();while(1){Key_Proc(); Seg_Proc();Led_Proc();}
}
关键字:南充房产网二手房_比地招标网官网_网站推广策划书范文_搜索引擎排行榜

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: