蓝桥杯单片机第三届国赛题目-门禁系统
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[以上是关于蓝桥杯单片机第三届国赛题目-门禁系统的主要内容,如果未能解决你的问题,请参考以下文章