第十五届单片机模拟考试II

题目

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

按键功能

对于这种一个按键对应一个值的题目,我们直接修改按键底层。

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();
	}
}
相关推荐
欢乐熊嵌入式编程2 小时前
智能手表固件升级 OTA 策略文档初稿
嵌入式硬件·学习·智能手表
欢乐熊嵌入式编程2 小时前
智能手表 MCU 任务调度图
单片机·嵌入式硬件·智能手表
【云轩】2 小时前
电机密集型工厂环境下的无线通信技术选型与优化策略
经验分享·嵌入式硬件
sword devil9003 小时前
将arduino开发的Marlin部署到stm32(3D打印机驱动)
stm32·单片机·嵌入式硬件
GodKK老神灭3 小时前
STM32 变量存储
stm32·单片机·嵌入式硬件
木宁kk3 小时前
51单片机引脚功能概述
单片机·嵌入式硬件
JANYI20183 小时前
嵌入式MCU和Linux开发哪个好?
linux·单片机·嵌入式硬件
sword devil9005 小时前
Arduino快速入门
stm32·单片机·嵌入式硬件
GodKK老神灭5 小时前
STM32实现循环队列
stm32·单片机·嵌入式硬件
不脱发的程序猿7 小时前
从MCU到SoC的开发思维转变
单片机·嵌入式硬件