题目




这道题的难度就是密码的输入。但是其实也不是很难
按键功能

对于这种一个按键对应一个值的题目,我们直接修改按键底层。
cpp
#include <Key.h>
unsigned char Key_Read(){
unsigned char temp = 0;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;
if(P33 == 0) temp = 11;//4确认
if(P32 == 0) temp = 12;//5清除
if(P31 == 0) temp = 1;//6
P44 = 1;P42 = 0;P35 = 1;P34 = 1;
if(P33 == 0) temp = 8;//8
if(P32 == 0) temp = 5;//9
if(P31 == 0) temp = 2;//10
P44 = 1;P42 = 1;P35 = 0;P34 = 1;
if(P33 == 0) temp = 9;//12
if(P32 == 0) temp = 6;//13
if(P31 == 0) temp = 3;//14
P44 = 1;P42 = 1;P35 = 1;P34 = 0;
if(P33 == 0) temp = 10;//16
if(P32 == 0) temp = 7;//17
if(P31 == 0) temp = 4;//18
return temp;
}
因为按键对应的值变量默认就是0,所以我的按键底层从1开始到10,对应的就是0~9,避免了0的直接出现。
S4确认密码,密码正确进入存储界面,错误清除数组回到初始状态。
S5清除按键,回到没有输入的情况。
定义我们定义一个清除函数,来辅助回到初始没有输入的状态。
根据显示功能那边的初始状态来完成清除函数。
cpp
//清除密码
void clean(){
unsigned char i;
mima_index = 0;
for(i=0;i<8;i++){
mima[i] = 12;//-清除
}
}
按下S4比较密码,循环数组只要有一位不相等,那就是密码错误,返回初始界面,全部正确才能进入存储界面。定义一个标志位来进入存储界面.
接着就是1~10也就是0~9的输入,高位熄灭,共输入8位。
每次输入的一位在最右边,前面的输入左移一位,那么我们就把之前的数据左移,最后一位的数据用当前获取的值写入。这边记得最多输入8位,多输入的数据我们应该不让他们进来,设置输入上限。(测评会多按一次8,来检测这个地方有没有输入位数限制)
cpp
/*按键函数区域*/
void Key_Proc(){
unsigned char i;
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 == 11){//s4确认
if(Seg_Mode == 0){
for(i=0;i<8;i++){
if(mima_recode[i] == mima[i]) prove++;//密码正确
}
if(prove == 8){//密码全部正确
L3_start = 0;
mima_flag = 1;
}
else{
mima_flag = 0;//密码错误
L3_start = 1;//闪烁L3计时
clean();
}
prove = 0;
}
}
if(Seg_Mode == 0){//在密码输入界面
if(Key_Down == 12){//s5消除
clean();
}
if(Key_Down<=10&&Key_Down>=1){//正常输入
if(mima_index<=7){//输入完成八位不让再次输入
for(i=0;i<mima_index;i++){//所有密码往前移位一位
mima[7+i-mima_index] = mima[8+i-mima_index];
}
mima[7] = Key_Down-1;//输入最后一位密码
for(i=0;i<8;i++){
if(mima[i] == 12){
mima[i] = 10;
};//高位熄灭
}
mima_index++;//设置上限
}
}
}
}
显示功能

密码输入显示的内容就是我们的数组直接显示,数组的处理我们在按键那边完成了,这边直接输入就行。标志位进入存储界面,读取显示存储正确值。5s后返回密码输入界面,并且初始化密码界面,所以在标志位起作用时进入存储界面,不起作用的时候正常显示密码界面。
题目给出了正确值的范围,我们在判断密码正确之后正确值加一,再写入eeprom里面,下次上电的时候读取到存储的正确值。
cpp
/*数码管显示区域*/
void Seg_Proc(){
//unsigned char i;
if(Seg_Slow) return;
Seg_Slow = 1;
if(mima_flag){//密码输入正确,进入存储界面
mima_flag = 0;
time_start = 1;
right = right == 255?255:right+1;//范围0~255
Seg_Mode = 1;
EE_Write(&right,0,1);
}
if(Seg_Mode == 0){//输入密码界面
Seg_Buf[0] = mima[0];
Seg_Buf[1] = mima[1];
Seg_Buf[2] = mima[2];
Seg_Buf[3] = mima[3];
Seg_Buf[4] = mima[4];
Seg_Buf[5] = mima[5];
Seg_Buf[6] = mima[6];
Seg_Buf[7] = mima[7];
}
else{//存储界面
Seg_Buf[0] = 11;//E
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = 10;
Seg_Buf[5] = right>99?right/100:10;
Seg_Buf[6] = right>9?right/10%10:10;
Seg_Buf[7] = right%10;
}
}
记录功能

判断的实现我们在按键函数里面完成了。
cpp
if(mima_flag){//密码输入正确,进入存储界面
mima_flag = 0;
time_start = 1;
right = right == 255?255:right+1;//范围0~255
Seg_Mode = 1;
EE_Write(&right,0,1);
}
Led指示功能
L1界面指示灯,L2也算是存储界面的指示灯,点亮时间和前提和进入显示界面一样的。
L8密码错误有效,1s闪烁,密码正确就取消闪烁。
cpp
/*Led函数区域*/
void Led_Proc(){
Led_Buf[1] = time_start;//密码正确L2点亮5s
Led_Buf[0] = (Seg_Mode == 0);
Led_Buf[2] = L3_flag;
}
这题的难点就在密码的写入时的数码管显示。
完整主函数
cpp
/*头文件区域*/
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Seg.h>
#include <Key.h>
#include <Led.h>
#include <iic.h>
/*参数变量区域*/
unsigned char Key_Slow,Seg_Slow;
unsigned char Key_Down,Key_Up,Key_Old,Key_Val;
unsigned char Seg_Pos;
//数组
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Point[8] = {0,0,0,0,0,0,0,0};
unsigned char Led_Buf[8] = {0,0,0,0,0,0,0,0};
//标志位
unsigned int Time_5s;
unsigned int Time_1s;
bit time_start;
bit mima_flag;//密码正确标志位,默认错误不仅存储界面
unsigned char prove;
bit L3_start;
bit L3_flag;
//数据
unsigned char mima_index;//密码数组标志位
unsigned char mima[8] = {12,12,12,12,12,12,12,12};//密码是八位
unsigned char mima_recode[8] = {1,2,3,4,5,6,7,8};//记录密码
unsigned char right = 0;
unsigned char Seg_Mode;//0密码输入,1密码存储
//清除密码
void clean(){
unsigned char i;
mima_index = 0;
for(i=0;i<8;i++){
mima[i] = 12;//-清除
}
}
/*按键函数区域*/
void Key_Proc(){
unsigned char i;
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 == 11){//s4确认
if(Seg_Mode == 0){
for(i=0;i<8;i++){
if(mima_recode[i] == mima[i]) prove++;//密码正确
}
if(prove == 8){//密码全部正确
L3_start = 0;
mima_flag = 1;
}
else{
mima_flag = 0;//密码错误
L3_start = 1;
clean();
}
prove = 0;
}
}
if(Seg_Mode == 0){//在密码输入界面
if(Key_Down == 12){//s5消除
clean();
}
if(Key_Down<=10&&Key_Down>=1){//正常输入
if(mima_index<=7){//输入完成八位不让再次输入
for(i=0;i<mima_index;i++){//所有密码往前移位一位
mima[7+i-mima_index] = mima[8+i-mima_index];
}
mima[7] = Key_Down-1;//输入最后一位密码
for(i=0;i<8;i++){
if(mima[i] == 12){
mima[i] = 10;
};//高位熄灭
}
mima_index++;//设置上限
}
}
}
}
/*数码管显示区域*/
void Seg_Proc(){
//unsigned char i;
if(Seg_Slow) return;
Seg_Slow = 1;
if(mima_flag){//密码输入正确,进入存储界面
mima_flag = 0;
time_start = 1;
right = right == 255?255:right+1;//范围0~255
Seg_Mode = 1;
EE_Write(&right,0,1);
}
if(Seg_Mode == 0){//输入密码界面
Seg_Buf[0] = mima[0];
Seg_Buf[1] = mima[1];
Seg_Buf[2] = mima[2];
Seg_Buf[3] = mima[3];
Seg_Buf[4] = mima[4];
Seg_Buf[5] = mima[5];
Seg_Buf[6] = mima[6];
Seg_Buf[7] = mima[7];
}
else{//存储界面
Seg_Buf[0] = 11;//E
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = 10;
Seg_Buf[5] = right>99?right/100:10;
Seg_Buf[6] = right>9?right/10%10:10;
Seg_Buf[7] = right%10;
}
}
/*Led函数区域*/
void Led_Proc(){
Led_Buf[1] = time_start;//密码正确L2点亮5s
Led_Buf[0] = (Seg_Mode == 0);
Led_Buf[2] = L3_flag;
}
/*定时器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(++Key_Slow == 50) Key_Slow = 0;
if(++Seg_Slow == 200) Seg_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]);
if(time_start){
if(++Time_5s == 5000){//5s后返回密码输入界面
Time_5s = 0;//清空计时
time_start = 0;//停止计时
mima_flag = 0;//重置标志位
Seg_Mode = 0;//退出存储界面
clean();//清除密码数组
}
}
else Time_5s = 0;//清空计时
if(L3_start){
if(++Time_1s == 1000){
Time_1s = 0;
L3_flag ^= 1;
}
}
else{
Time_1s = 0;
L3_flag = 0;
}
}
/*主函数区域*/
void main(){
Sys_Init();
Timer0_Init();
//EE_Write(&right,0,1);
EE_Read(&right,0,1);
while(1){
Key_Proc();
Seg_Proc();
Led_Proc();
}
}