第十五届单片机模拟考试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();
	}
}
相关推荐
清风6666667 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm8 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu11 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客12 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭12 小时前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽13 小时前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊14 小时前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头15 小时前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭15 小时前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗15 小时前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件