蓝桥杯单片机第三届国赛题目-门禁系统

Posted WILLPOWER-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯单片机第三届国赛题目-门禁系统相关的知识,希望对你有一定的参考价值。

题目

在这里插入图片描述

文件树

在这里插入图片描述

代码

init.c

#include "init.h"

code uchar table[][4] = {0, 1, 1, 1,
						 1, 0, 1, 1,
	                     1, 1, 0, 1,  
						 1, 1, 1, 0};
extern uchar buffer[8];
extern uint distance;
void SL(uchar _device, uchar _data){
	P0 = _data; SEL(_device);
}

void Timer1Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x40;		//设置定时初值
	TH1 = 0xA2;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;
	EA = 1;
}

uchar GetKey(){
	uchar i;
	C1 = 1; C2 = 1; C3 = 1; C4 = 1;
	for(i = 0; i < 4; i++){
		R1 = table[i][0]; R2 = table[i][1];
		R3 = table[i][2]; R4 = table[i][3];
		if(C1 == 0) return 1 + i*4;
		if(C2 == 0) return 2 + i*4;
		if(C3 == 0) return 3 + i*4;
		if(C4 == 0) return 4 + i*4;
	}
	return 0;
}
uchar FR(float _data, uchar _dig){
	uint m = 1;
	while(_dig--){
		m = m * 10;
	}
	return (uint)_data/m%10;
}
void Bf(uchar _0, uchar _1, uchar _2, uchar _3,
								uchar _4, uchar _5, uchar _6, uchar _7){
	buffer[0] = _0; buffer[1] = _1; buffer[2] = _2; buffer[3] = _3;
	buffer[4] = _4; buffer[5] = _5; buffer[6] = _6; buffer[7] = _7;
}
								
void TimeRun(t_delay* time){
	if(time->cnt++ < time->max);
	else{
		time->cnt = 0;
		time->ok = 1;
	}
}

void Delay14us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 39;
	while (--i);
}

void Sonic_Start(){
	uchar cnt = 10;
	while(cnt--){
		ST = 1;
		Delay14us();
		ST = 0;
		Delay14us();
	}
}
void Sonic(){
	uint time;
	CH = 0; CL = 0; CR = 1;
	Sonic_Start();
	while((SR) && (CF == 0));
	CR = 0;
	if(CF){CF = 0; distance = 9999;}
	else{
		time = ((uint)CH<<8) | CL;
		distance = time*0.017/12;
	}
}
uchar Check(uchar* p1, uchar* p2){
	uchar i;
	for(i = 0; i < 6; i++){
		if(*p1 != *p2){return 0;}
		else{
			p1++; p2++;
		}
	}
	return 1;
}
void Copy(uchar* p1, uchar* p2){
	uchar i;
	for(i = 0; i < 6; i++){
		*p2 = *p1;
		p1++; p2++;
	}
}

main.c

#include "init.h"
code uchar CA[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,\\
				   0x92, 0x82, 0xf8, 0x80, 0x90,\\
				   0xff, 0xbf
};
uchar buffer[] = {F_SEP, F_SEP, F_C, F_C, F_C, F_C, F_C, F_C};
uchar curDig = 0;
code enum{LED = 4, EXT, SEL, CODE};
code uchar clear[] = {F_C, F_C, F_C, F_C, F_C, F_C};
enum{KS_GT, KS_AS, KS_WA}keyState = KS_GT;
uchar key, tmpKey, keyCnt;
t_delay delay_200 = {200 ,0, 0};
t_delay delay_500 = {500 ,0, 0};
t_delay delay_Beep = {1500 ,0, 0};
t_delay delay_Relay = {2500 ,0, 0};
uint distance;
uchar time[3];
enum{S_AUTO, S_CODE}gloSta = S_CODE;
uchar sonicEnable = 0;
uchar codeCnt = 0;
uchar errorCnt = 0;
bit codeOk = 0;
bit beepEnable = 0; 
bit relayEnable = 0;
uchar codedata[] = {6,5,4,3,2,1};


void Timer1Hanle() interrupt 3{
	SL(CODE, 0xff); SL(SEL, 1 << curDig); SL(CODE, CA[buffer[curDig]]);
	curDig = (curDig + 1)%8;
	switch(keyState){
		case KS_GT:
			    keyCnt = 0;tmpKey = GetKey();keyState = KS_AS;
		break;
		
		case KS_AS:
				if(keyCnt++ < 10);
				else if(tmpKey == GetKey()){
					if(tmpKey != key){
						key = tmpKey;keyState = KS_WA;
					}
					else{
						keyState = KS_GT;
					}
				}
				else{
					keyState = KS_GT;
				}
		break;
	}
	TimeRun(&delay_200);
	TimeRun(&delay_500);
	if(delay_Beep.ok == -1)
	TimeRun(&delay_Beep);
	if(delay_Relay.ok == -1)
	TimeRun(&delay_Relay);
}

void Sensor(){
	if(delay_200.ok){
		delay_200.ok = 0;
		if(sonicEnable)
			Sonic();
			//如果小于30cm并且继电器没有开启并且在自动门模式则开启继电器
			if((distance < 30) && (delay_Relay.ok != -1) && (gloSta == S_AUTO)){
				RLON;
				delay_Relay.ok = -1;
			}
		DS1302_Read();
		//通过时间判断处于哪个模式
		if((time[0] == 0) && (time[1] == 0) && time[2] == 7){
			gloSta = S_AUTO;
			sonicEnable = 1;
		}
		if((time[0] == 0) && (time[1] == 0) && time[2] == 22){
			gloSta = S_CODE;
			sonicEnable = 0;
		}
		//如果是自动模式,则显示时间
		if(gloSta == S_AUTO){
		Bf(FR(time[2],1),FR(time[2],0),F_SEP,
		   FR(time[1],1),FR(time[1],0),F_SEP,
		   FR(time[0],1),FR(time[0],0));
		}
	}
	if(delay_Beep.ok == 1){
		delay_Beep.ok = 0;
		BPOFF;RLOFF;
	}	
	if(delay_Relay.ok == 1){
		delay_Relay.ok = 0;
		RLOFF;
	}		
}
void main(){
		BPOFF; RLOFF;
		SL(LED, 0xff);
		Timer1Init();
		CMOD |= 0x08;
		DS1302_init(06, 59, 00);
		CODE_Read(0, &codedata[0]);
  while(1){
			Sensor();
			if(keyState == KS_WA){
				//如果是手动密码模式
				if(gloSta == S_CODE){
					//如果按键处于0-9之间
					if(key < 11 && key > 0){
						//如果小于六位,则每次将按键值显示,并且按键计数+1
						if(codeCnt < 6){
							buffer[codeCnt+2] = key - 1;
							codeCnt++;
						}	
					}
					//设置按键
					else if(key == 11){
						if(WAITINPUT){
							//进入输入旧密码界面
							Copy(&clear[0],&buffer[2]);
							buffer[0] = F_C;
							codeCnt = 0;
							errorCnt = 0;
						}
					}
					//如果是确认按键
					else if(key == 15){
						//如果是等待输入,则确认按键是确认当前输入密码
						if(WAITINPUT){
							//检查密码是否正确
							if(Check(&buffer[2], &codedata[0])){
								//如果正确,打开继电器
								RLON;
								delay_Relay.ok = -1;
								errorCnt = 0;
							}
							//如果错误
							else{
									//如果错误次数小于3,错误次数+1
									if(errorCnt < 3){
										errorCnt++;
									}
									//否则响起蜂鸣器
									else{
										errorCnt = 0;
										BPON;RLOFF;
										delay_Beep.ok = 1;
								}
							}
						}
						//如果是输入旧密码界面
						else if(OLDCODE){
							//检查密码是否正确
							if(Check(&buffer[2], &codedata[0])){
								//如果正确,进入输入新密码状态
									buffer[0] = F_SEP;buffer[1] = F_C;
									codeCnt = 0;
									errorCnt = 0;
							}
							//如果错误
							else{
									//如果错误次数小于3,错误次数+1
									if(errorCnt < 3){
										errorCnt++;
									}
									//否则响起蜂鸣器,!并且退出修改密码功能
									else{
										errorCnt = 0;
										BPON;RLOFF;
										delay_Beep.ok = 1;
										buffer[0] = F_SEP;buffer[1] = F_SEP;
										codeCnt = 0;
								}
							}
						}
						//如果是输入新密码界面
						else if(NEWCODE){
							//检查密码是否为6位
							if(codeCnt == 6){
								Copy(&buffer[2], &codedata[0]);
								buffer[0] = F_SEP;buffer[1] = F_SEP;
								codeCnt = 0;
								errorCnt = 0;
							//这里我发现写一次有问题,我就重复写三次了
								CODE_Write(0,&codedata[0]);
								CODE_Write(0,&codedata[0]);
								CODE_Write(0,&codedata[0]);
							}
						}
						//不管哪种情况按下确认按键后,都会清空密码
							Copy(&clear[0], &buffer[2]);
							codeCnt = 0;
						}
					//复位按键
					else if(key == 12){
						uchar defaultcode[] = {6,5,4,3,2,1};
						Copy(&defaultcode[0], &codedata[0]);
					//这里我发现写一次有问题,我就重复写三次了
						CODE_Write(0,&codedata[0]);
						CODE_Write(0,&codedata[0]);
						CODE_Write(0,&codedata[0]);
					}
					//退出按键
					else if(key == 16){
						if((OLDCODE) || (NEWCODE)){
							errorCnt = 0;
							buffer[0] = F_SEP;buffer[1] = F_SEP;
							codeCnt = 0;
							Copy(&clear[以上是关于蓝桥杯单片机第三届国赛题目-门禁系统的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯单片机国赛第三届(超级详细注释)

蓝桥杯单片机国赛第三届(超级详细注释)

蓝桥杯单片机第六届国赛题目-智能物料传送系统

蓝桥杯单片机第六届国赛题目-智能物料传送系统

蓝桥杯单片机第七届国赛题目-电压频率采集设备

蓝桥杯单片机第七届国赛题目-电压频率采集设备