第十五届单片机模拟考试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();
	}
}
相关推荐
爱喝西北风的东北风1 小时前
状态机思想编程
单片机·嵌入式硬件·fpga开发
柒月玖.3 小时前
基于AT89C51单片机的加减乘除液晶计算机设计
单片机·嵌入式硬件
剑鞘的流苏3 小时前
DC-DC电路和LDO电路
单片机·嵌入式硬件
CDialog6 小时前
qemu仿真调试esp32,以及安装版和vscode版配置区别
单片机·嵌入式硬件
南梦也要学习6 小时前
STM32江科大----IIC
stm32·单片机·嵌入式硬件
狄加山6757 小时前
STM32 基础1
stm32·单片机·嵌入式硬件
lzb7598 小时前
第16届蓝桥杯单片机模拟试题Ⅱ
单片机·蓝桥杯
程序员JerrySUN9 小时前
深入解析嵌入式Linux系统架构:从Bootloader到用户空间
linux·运维·驱动开发·嵌入式硬件·系统架构
march_birds9 小时前
Zephyr与Linux核心区别及适用领域分析
c语言·开发语言·单片机·系统架构
坏柠21 小时前
深入浅出SPI通信协议与STM32实战应用(W25Q128驱动)(实战部分)
stm32·单片机·嵌入式硬件