电路原理图:
pcb布线:
使用说明
一、实现功能:5张卡
1、用户密码以及IC卡号和IC卡刷入序列号,保存到STC12C5A60S2的EEPROM中,掉电数据保存功能。
2、支持非接触式IC卡授权功能,可连续授权(授权需输入管理员密码)。
3、支持手动选卡销卡,支持单卡刷入销卡,支持注销所有卡(注销所有卡需输入管理员密码)
4、自动识别非接触式IC卡功能。如刷授权过的IC卡,提示“欢迎光临”,显示卡号并且开门,5秒后自动关门。如果刷未授权的IC卡,提示“该卡未授权”,显示卡号不开门。
5、如忘记携带IC卡,可通过键盘手动输入用户密码。密码输入错误显示器会出现错误提示且继电器不工作(不开门);若密码输入正确则继电器工作(开门)。
6、支持手动更改用户密码(更改用户密码需输入管理员密码)
7、支持无卡时钟显示功能(功能:显示年月日时分秒周,阴历,天干地支,生肖,温度,可改时间,具有掉电走时功能)
二、按键定义
如图示:采用4X4键盘输入,键盘对应名称如下:
1 2 3 A
4 5 6 B
7 8 9 C
* 0 # D
其中, 【0—9】为数字键,用于输入相应的密码,
【*】号键为清除所有卡
【A】键为返回功能
|->长按A键2秒可调时间,此时按下1键为选择修改项,按下2键为加,按下3键为减,再次长按A键退出时间修改。
【B】键为授权IC卡功能->提示输入管理员密码->输入管理员密码->刷入IC卡号->提示授权成功->是否继续授权->按A键返回
【C】键为注销IC卡功能->提示刷入IC卡号->提示注销成功->按A键返回
|->或按下#键 手动选择卡注销->按D键确认并退出
【D】键为确认功能
【#】号键为手动输入密码功能->提示输入密码->输入密码
|->改密码->提示输入管理员密码->输入管理员密码->改用户密码->输入用户密码->确认并再次输入->修改成功
提示:所有的输密码和改密码功能,输入三次错误后则退出输入或修改功能,输入或修改失败。
单片机源程序如下:
- /*********************************
- 按键分布
- 1 2 3 A
- 4 5 6 B
- 7 8 9 C
- * 0 # D
- 其中, 【0—9】为数字键,用于输入相应的密码,
- 【*】号键为清除所有卡
- 【A】键为返回功能
- 【B】键为授权IC卡功能
- 【C】键为注销IC卡功能
- 【D】键为确认功能
- 【#】号键为手动输入密码功能
- 时钟功能调时说明:长按A键2秒可调时间,此时按下1键为选择修改项,按下2键为加,按下3键为减,再次长按A键退出时间修改
- ********************************************************************************************************/
- #include <stc12c5a60s2.h>
- #include <stdio.h>
- #include "spi.h"
- #include "12864.h"
- #include "eeprom.h"
- #include "mfrc522.h"
- #include "uart.h"
- #include "KEYBOARD.h"
- #include "clock.h"
- #include "ds1302.h"
- #define IAP_ADDRESS1 0x0100 //用户密码起始地址
- #define IAP_ADDRESS 0x0200 //IC卡序列号起始地址
- uchar code administer_key[]={0,0,0,};//管理员卡密码
- static uchar xdata IC_EEPROM[5][5];//存入EEPROM密码 每行前4位为卡号 第5位为卡片输入顺序号
- static uchar xdata User_len; //用户密码长度
- static uchar xdata Userpassword[16];//用户密码
- static uchar xdata ICCODE[4];//返回卡号4位
- static uchar xdata Rec_Buffer[REC_BUFFER_SIZE];//串口接收缓冲区
- static uchar xdata RELAY_NUM=0;//开门计时变量
- static uchar xdata IC_NUM=0;//刷入卡的顺序
- static uchar Recvd_Count;//串口已接收数据的个数
- bit lock_ok=0;//密码匹配标记
- bit shouquan_flag=0;//授权标记
- bit shoudongshuru_flag=0; //手动输入密码标记
- bit IC_flag=0; //寻卡标记
- //bit shanshuo;//较表时闪烁用
- void io_init()
- {
- //P0M1=0XFF;//开漏模式
- //P0M0=0XFF;
- P1M1=0XFF;//P1.7-P1.3开漏模式用于RC522;
- P1M0=0XFF;
- P2M1=0X00;//P2.7,P2.0推挽输出模式
- P2M0=0X81;
- //P3M1=0X00;
- //P3M0=0XFF;
- P4SW=0x70;
- P4M1=0X00;//推挽模式
- P4M0=0XFF;
- }
- /****************************************************
- 函数名称:bit Auto_Reader(void)
- 入口参数:无
- 出口参数:有卡返回0,无卡返回1
- 功能:寻卡
- 寻卡并在液晶屏上显示序列号
- ****************************************************/
- bit Auto_Reader(void)
- {
- uchar temp[4];
- // uchar g_ucTempbuf1[16];
- // uchar code DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //初始密码
- uchar i;
- uchar ID_ASC[8];
- if (MI_OK==PcdRequest(PICC_REQALL,temp))//寻卡,输出为卡类型//*PICC_REQALL=0x52:寻天线区内所有符合14443A标准的卡 PICC_REQIDL=0x26:只寻未进入休眠状态的卡
- {
- if (MI_OK==PcdAnticoll(temp))//防冲撞处理,输出卡片序列号,4字节
- if (MI_OK==PcdSelect(temp)) //选择卡片,输入卡片序列号,4字节
- //if (MI_OK==PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, temp)) //验证密码 输出卡片序列号
- //if(MI_OK==PcdRead(0, g_ucTempbuf1))//卡中第一块数据内容
- {
- IC_flag=1;
- lcd_clear();
- display_GB2312_string(3,1,"IC序列号:");
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- { ICCODE[i]=temp[i];
- if(temp[i]/16>9) ID_ASC[i*2]=temp[i]/16+'7';
- else ID_ASC[i*2]=temp[i]/16+'0';
- if(temp[i]%16>9) ID_ASC[i*2+1]=temp[i]%16+'7';
- else ID_ASC[i*2+1]=temp[i]%16+'0';
- }
- display_GB2312_string(5,1,ID_ASC);
- }
- return 0;
- }
- else
- {
- BELL=0;return 1;
- }
- }
- /****************************************************
- 函数名称:bit administer(void)
- 入口参数:无
- 出口参数:密码正确返回0,错误返回1
- 全局变量shouquan_flag :允许授权shouquan_flag=0; 不允许授权shouquan_flag=1;
- 功能:管理员
- 验证系统密码 用于授权管理、注销全部卡管理、修改用户密码,三次输入错误返回
- 调用函数:EEPROM.C 12864.c KeyPro(); bit Auto_Reader(void);
- ****************************************************/
- bit administer(void)
- {
- uchar asterisk='*';
- uchar spacing =' ';
- uchar temp=0,error=0,j=0,num=0,i=0,k=0;//
- bit Flag; //比较位置
- unsigned char passwordlength,PLEN; //输入密码长度,实际密码长度
- unsigned char passwordtemp[16]; //最大输入16个
- PLEN=sizeof(administer_key)/sizeof(administer_key[0]);//用于计算出实际密码长度
- display_GB2312_string(1,1,"请输入管理员密码");
- while(shouquan_flag==1)
- {
- temp=KeyPro();
- if(temp!=0xff)
- {
- if(i==0) //输入是第一个字符的时候需要把改行清空,方便观看密码
- display_GB2312_string(3,1," ");//清除该行
- if((i<16)&&(temp<=9))
- {
- passwordtemp[i]=temp;
- display_GB2312_string(3,i*8+1,&asterisk);//输入的密码用"*"代替
- i++; //输入数值累加
- }
- if('*'==temp&&i>0)
- {
- i--;
- for(k=i;k<16;k++)
- display_GB2312_string(3,k*8,&spacing);//输入用空格代替
- }
- if('A'==temp)//退出
- {
- display_GB2312_string(3,1," ");//清除该行
- shouquan_flag=1;
- return 0;
- }
- if(('D'==temp)|| (i==16))//输入按键值D或者密码输入到最大值16,表示输入结束,需要进行比对
- {
- passwordlength=i; //计算输入密码长度
- i=0; //计数器复位
- if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误
- {
- Flag=1;//先把比较位置1
-
- for(j=0;j<PLEN;j++)//循环比较8个数值,如果有一个不等 则最终Flag值为0
- Flag=Flag&&(passwordtemp[j]==administer_key[j]);//比较输入值和已有密码
- }
- if(Flag)//如果比较全部相同,标志位置1
- {
- pass();
- lcd_clear();
- error=0;//输入正确则次数清零,重新计数
- Flag=0; //清除正确标志
- shouquan_flag=0;
- return 0;
- }
- else
- {
- display_GB2312_string(3,1," ");//清除该行
- display_GB2312_string(3,1,"Wrong! Retry!");//密码错误,提示重新输入
- error++;//连续输入错误,则次数累加
- if(error==3)
- {
- display_GB2312_string(3,1," ");//清除该行
- display_GB2312_string(3,1,"Wrong 3 times!");//密码错误,提示重新输入
- delayms(1500);
- shouquan_flag=1;
- return 0;
- //while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
- }
- }
- }
- }
- }
- }
- /****************************************************
- 函数名称:void shouquan(uchar key)
- 入口参数:key->按键值
- 出口参数:无
- 功能:授权
- 按下B键进入授权
- 流程->提示输入系统密码->输入系统密码->刷入IC卡号->提示是否继续授权->按A键返回 (授权期间均可按A键返回)
- 调用函数:EEPROM.C 12864.c KeyPro(); bit administer(); bit Auto_Reader(void);
- ****************************************************/
- void shouquan(uchar key)
- {
- uchar j=0,k=0,flag,flag1;
- if(key=='B')//授权检测
- {
- lcd_clear();
- //Sent_Byte(IC_NUM);
- shouquan_flag=1;
- while(administer()); //管理员返回0,密码正确shouquan_flag=0
- display_GB2312_string(1,1,"请刷入授权IC卡号");//密码正确显示的信息
- if(IC_EEPROM[4][4]==5&&(shouquan_flag==0))//如果最后一位不是0XFF说明有卡刷入
- {
- display_GB2312_string(1,1,"IC卡超出5张请按C");
- display_GB2312_string(3,1,"IC卡超出5张请按*");
- shouquan_flag=1;
- delayms(2000);
- }
- else if(shouquan_flag==0) //刷卡授权
- {
- flag1=1;
- while(IC_NUM<5&&flag1==1)
- {
- flag=1;
- while(flag) //刷入卡号,正确返回0,退出 并在LCD显示
- {
- flag=Auto_Reader();
- if('A'==KeyPro())//退出
- {
- flag=1;
- flag1=0;
- break;
- }
- }
- if(flag==0)
- {
- //delayms(1000);
- IC_NUM++;
- for(j=0;j<5;j++)
- {
- if(j<4)IC_EEPROM[IC_NUM-1][j]=ICCODE[j];//卡号
- else IC_EEPROM[IC_NUM-1][j]=IC_NUM;//刷入的顺序
- //Sent_Byte(IC_EEPROM[IC_NUM-1][j]);
- }
- IapEraseSector(IAP_ADDRESS);//清除数据
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IapProgramByte(IAP_ADDRESS+j*5+k,IC_EEPROM[j][k]);//写入数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- pass();
- if(IC_NUM<5)
- {
- delayms(1000);
- lcd_clear();
- display_GB2312_string(1,1,"IC卡授权成功 ");
- display_GB2312_string(3,1,"是否继续刷入 ");
- display_GB2312_string(5,1,"继续请刷卡 ");
- display_GB2312_string(7,1,"停止请按’A‘键 ");
- }
- else
- {
- delayms(1000);
- lcd_clear();
- display_GB2312_string(1,1,"IC卡存储到5张 ");
- delayms(2000);
- }
- }
- }
- }
- }
- }
- /****************************************************
- 函数名称:void zhuxiao_all(uchar key)
- 入口参数:key->按键值
- 出口参数:无
- 功能:注销所有IC卡
- 按下*键为注销IC卡功能->提示输入系统密码->输入系统密码->确定注销全部卡->注销成功->自动返回 (注销期间均可按A键返回)
- 调用函数:EEPROM.C 12864.c KeyPro(); administer();
- ****************************************************/
- void zhuxiao_all(uchar key)
- {
- uchar j,k;
- if(key=='*')
- {
- lcd_clear();
- shouquan_flag=1;
- while(administer()); //管理员返回0,密码正确shouquan_flag=0
- key=0xff;
- while(key!='*'&&shouquan_flag==0)
- {
- if(key=='A') break;
- key=KeyPro();
- display_GB2312_string(1,1,"是否注销所有IC卡");
- display_GB2312_string(3,1,"确定请按'*'号键");
- }
- if(shouquan_flag==0&&key=='*')
- { lcd_clear();
- IC_NUM=0;
- pass();
- display_GB2312_string(1,1,"注销所有IC卡 ");
- delayms(1000);
- IapEraseSector(IAP_ADDRESS);//清除数据
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//4列
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*4+k);//读出数据
- display_GB2312_string(1,1,"注销成功 ");
- delayms(1000);
- }
- }
- }
- /****************************************************
- 函数名称:void shoudong_zhuxiao_one(uchar key)
- 入口参数:key->按键值
- 出口参数:无
- 功能:手动注销单张IC卡
- 按#号键手动销卡
- 流程->提示按下对应刷入的卡顺序号->按下1-5按键选择对应卡->提示确认注销按相应按键->按D键确认并返回 (期间按A键不可退出手动销卡模式)
- 调用函数:EEPROM.C 12864.c KeyPro();
- ****************************************************/
- void shoudong_zhuxiao_one(uchar key)
- {
- uchar key2,j,k,v,i;
- uchar ID_ASC[9]={1,1,};
- if(key=='#')
- {
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- lcd_clear();
- key2=0xff;
- display_GB2312_string(1,1,"按对应顺序号销卡");
- while(key2!='D')//确认
- {
- display_GB2312_string(3,1,"确认并退出请按D");
- key2=KeyPro();
- if(key2==1)
- {
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- {
- if(IC_EEPROM[0][i]/16>9) ID_ASC[i*2]=IC_EEPROM[0][i]/16+'7';
- else ID_ASC[i*2]=IC_EEPROM[0][i]/16+'0';
- if(IC_EEPROM[0][i]%16>9) ID_ASC[i*2+1]=IC_EEPROM[0][i]%16+'7';
- else ID_ASC[i*2+1]=IC_EEPROM[0][i]%16+'0';
- }
- //Sent_Buffer(ID_ASC,8);
- display_GB2312_string(5,1,ID_ASC);
- display_GB2312_string(7,1,"注销按1,返回按A ");
- key2=0xff;
- while(key2!=1)
- {
- key2=KeyPro();
- if(key2=='A')break;//退出
- }
- pass();
- if(key2==1)for(j=0;j<5;j++)IC_EEPROM[0][j]=0xff;
- }
- else if(key2==2)
- {
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- {
- if(IC_EEPROM[1][i]/16>9) ID_ASC[i*2]=IC_EEPROM[1][i]/16+'7';
- else ID_ASC[i*2]=IC_EEPROM[1][i]/16+'0';
- if(IC_EEPROM[1][i]%16>9) ID_ASC[i*2+1]=IC_EEPROM[1][i]%16+'7';
- else ID_ASC[i*2+1]=IC_EEPROM[1][i]%16+'0';
- }
- //Sent_Buffer(ID_ASC,8);
- display_GB2312_string(5,1,ID_ASC);
- display_GB2312_string(7,1,"注销按2,返回按A ");
- key2=0xff;
- while(key2!=2)
- {
- key2=KeyPro();
- if(key2=='A')break;//退出
- }
- pass();
- if(key2==2)for(j=0;j<5;j++)IC_EEPROM[1][j]=0xff;
- }
- else if(key2==3)
- {
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- {
- if(IC_EEPROM[2][i]/16>9) ID_ASC[i*2]=IC_EEPROM[2][i]/16+'7';
- else ID_ASC[i*2]=IC_EEPROM[2][i]/16+'0';
- if(IC_EEPROM[2][i]%16>9) ID_ASC[i*2+1]=IC_EEPROM[2][i]%16+'7';
- else ID_ASC[i*2+1]=IC_EEPROM[2][i]%16+'0';
- }
- //Sent_Buffer(ID_ASC,8);
- display_GB2312_string(5,1,ID_ASC);
- display_GB2312_string(7,1,"注销按3,返回按A ");
- key2=0xff;
- while(key2!=3)
- {
- key2=KeyPro();
- if(key2=='A')break;//退出
- }
- pass();
- if(key2==3)for(j=0;j<5;j++)IC_EEPROM[2][j]=0xff;
- }
- else if(key2==4)
- {
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- {
- if(IC_EEPROM[3][i]/16>9) ID_ASC[i*2]=IC_EEPROM[3][i]/16+'7';
- else ID_ASC[i*2]=IC_EEPROM[3][i]/16+'0';
- if(IC_EEPROM[3][i]%16>9) ID_ASC[i*2+1]=IC_EEPROM[3][i]%16+'7';
- else ID_ASC[i*2+1]=IC_EEPROM[3][i]%16+'0';
- }
- //Sent_Buffer(ID_ASC,8);
- display_GB2312_string(5,1,ID_ASC);
- display_GB2312_string(7,1,"注销按4,返回按A ");
- key2=0xff;
- while(key2!=4)
- {
- key2=KeyPro();
- if(key2=='A')break;//退出
- }
- pass();
- if(key2==4)for(j=0;j<5;j++)IC_EEPROM[3][j]=0xff;
- }
- else if(key2==5)
- {
- for(i=0;i<4;i++) //卡ID号转化成ASCII
- {
- if(IC_EEPROM[4][i]/16>9) ID_ASC[i*2]=IC_EEPROM[4][i]/16+'7';
- else ID_ASC[i*2]=IC_EEPROM[4][i]/16+'0';
- if(IC_EEPROM[4][i]%16>9) ID_ASC[i*2+1]=IC_EEPROM[4][i]%16+'7';
- else ID_ASC[i*2+1]=IC_EEPROM[1][i]%16+'0';
- }
- //Sent_Buffer(ID_ASC,8);
- display_GB2312_string(5,1,ID_ASC);
- display_GB2312_string(7,1,"注销按5,返回按A ");
- key2=0xff;
- while(key2!=5)
- {
- key2=KeyPro();
- if(key2=='A')break;//退出
- }
- pass();
- if(key2==5)for(j=0;j<5;j++)IC_EEPROM[4][j]=0xff;
- }
- display_GB2312_string(5,1," ");
- display_GB2312_string(7,1," ");
- }
- for(v=0,j=0;j<5;j++)//得到刷入的卡顺序号
- {
- if(0xff!=IC_EEPROM[j][4])
- {
- for(k=0;k<5;k++)
- {
- IC_EEPROM[v][k]=IC_EEPROM[j][k];//重新排列卡号
- //Sent_Byte(IC_EEPROM[v][k]);
- }
- v++;
- }
- }
- IC_NUM=v;//Sent_Byte(IC_NUM);
- for(j=0;j<5;j++)
- for(k=0;k<5;k++)
- {
- if(j>=IC_NUM)IC_EEPROM[j][k]=0XFF;
- else IC_EEPROM[j][4]=j+1;
- }
- IapEraseSector(IAP_ADDRESS);//清除数据
- delayms(10);
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IapProgramByte(IAP_ADDRESS+j*5+k,IC_EEPROM[j][k]);//写入数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- delayms(10);
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出卡数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- pass();
- }
- }
- /****************************************************
- 函数名称:void zhuxiao_one(uchar key)
- 入口参数:key->按键值
- 出口参数:无
- 功能:持卡或手动注销单张IC卡
- 按下C键进入持卡或手动注销单张IC卡
- 调用函数:EEPROM.C 12864.c KeyPro(); shoudong_zhuxiao_one();
- ****************************************************/
- void zhuxiao_one(uchar key)
- {
- uchar i,j,k,ok,flag,m=0,key1;
- if(key=='C')
- {
- // while(administer()); //管理员返回0,密码正确shouquan_flag=0
- lcd_clear();
- display_GB2312_string(1,1," 刷入注销卡 ");
- display_GB2312_string(3,1,"或按#键手动注销 ");
- flag=1;
- key1=0xff;
- while(flag==1&&key1!='A'&&key1!='#') //刷入卡号,正确返回0,退出 并在LCD显示
- {
- flag=Auto_Reader();
- key1=KeyPro();
- if('A'==key1&&key1=='#')//退出
- {
- flag=1;
- break;
- }
- }
- if(key1=='#')
- {
- shoudong_zhuxiao_one(key1);
- key1=0xff;
- }
- if(flag==0)//刷卡标记
- {
- //IC_flag=0;
- for(j=0;j<5;j++)//5行///比较刷入的是哪张卡
- {
- ok=1;
- for(k=0;k<4;k++)//4列
- {
- ok=ok&&(IC_EEPROM[j][k]==ICCODE[k]);
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- if(ok==1)
- {
- ok=0;
- m=IC_EEPROM[j][4]+0X30;
- display_GB2312_string(7,1,"注销卡序列号: ");
- display_GB2312_string(7,105,&m);
- pass();
- delayms(1000);
- m=IC_EEPROM[j][4];
- //Sent_Byte(n);
- break;
- //goto addr1;
- }
- }
- //addr1:
- if(ok==0) //重新排列对齐数据
- {
- ok=1;
- i=0;
- //Sent_Byte(n);
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- if(m==5)//如果是最后一张卡直接替换最后一个数据 前4个不用移位
- for(j=0;j<5;j++)
- IC_EEPROM[4][j]=0xff;//最后一个数据补oxff
- else //不是最后一个卡 则进行数据移位
- {
- for(j=0;j<5;j++)//得到刷入的卡顺序号
- {
- if(m==IC_EEPROM[j][4])i+=1;
- for(k=0;k<5;k++)
- {
- IC_EEPROM[j][k]=IC_EEPROM[i][k];//重新排列卡号
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- i++;
- }
- for(j=0;j<5;j++)IC_EEPROM[4][j]=0xff;//最后一个数据补oxff
- ok=1;
- for(j=0;j<5;j++)
- {
- ok=1;
- for(k=0;k<4;k++)
- ok=ok&&(IC_EEPROM[j][k]==0xff);
- if(ok==1) IC_NUM=IC_EEPROM[j][4]=0xff;//无数据的存储地址卡序号初始为0xff
- else IC_NUM=IC_EEPROM[j][4]=j+1;
- }
- }
- IapEraseSector(IAP_ADDRESS);//清除数据
- delayms(10);
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IapProgramByte(IAP_ADDRESS+j*5+k,IC_EEPROM[j][k]);//写入数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- delayms(10);
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//5列
- {
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出卡数据
- //Sent_Byte(IC_EEPROM[j][k]);
- }
- for(j=0;j<5;j++)
- if(IC_EEPROM[j][4]!=0xff) IC_NUM=IC_EEPROM[j][4];//读出卡刷入顺序
- if(IC_NUM==0xff)IC_NUM=0;
- //Sent_Byte(IC_NUM);
- }
- }
- }
- }
- /****************************************************
- 函数名称:bit shudongshuru(uchar key)
- 入口参数:key->按键值
- 出口参数:正确返回0,错误返回1
- 功能:手动输入用户密码、可改用户密码
- 按#键手动输入密码 *键后退清除一位 D键确定 A键退出 改用户密码时按B键授权后 方可更改
- 调用函数:EEPROM.C 12864.c KeyPro();
- ***************************************************/
- bit shudongshuru(uchar key)
- {
- uchar asteris='*';
- uchar spacin =' ';
- uchar key2=0,error=0,j=0,num=0,i=0,k=0,n=0;
- bit Flag; //比较相等标记
- unsigned char passwordlength; //输入密码长度,实际密码长度
- unsigned char passwordtemp[16]; //最大输入16个
- unsigned char passwordlast[16];
- if(key=='#')
- {
- lcd_clear();
- display_GB2312_string(1,1," 请输入密码 ");
- display_GB2312_string(3,1,"或按B授权改密码 ");
- shoudongshuru_flag=1;
- while(shoudongshuru_flag==1)
- {
- key2=KeyPro();
- if(key2=='A') return 1;
- if(key2!=0xff)
- {
- if(i==0) //输入是第一个字符的时候需要把改行清空,方便观看密码
- display_GB2312_string(5,1," ");//清除该行
- if((i<16)&&(key2<=9))
- {
- passwordtemp[i]=key2;
- // Sent_Byte(key2);
- //display_graphic_5x7(5,i*8+1,xing);//输入的密码用"*"代替
- display_GB2312_string(5,i*8+1,&asteris);//输入的密码用"*"代替
- i++; //输入数值累加
- }
- if('*'==key2&&i>0)
- {
- i--;
- for(k=i;k<16;k++)
- display_GB2312_string(5,k*8,&spacin);//输入用空格代替
- }
- if('A'==key2)//退出
- {
- lcd_clear();
- shoudongshuru_flag=0;
- return 0;
- }
- if(('D'==key2)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对
- {
- passwordlength=i; //计算输入密码长度
- if(passwordlength==User_len)//长度相等则比较,否则直接输出错误
- {
- Flag=1;//先把比较位置1
- for(j=0;j<User_len;j++)//循环比较数值,如果有一个不等 则最终Flag值为0
- {
- Flag=Flag&&(passwordtemp[j]==Userpassword[j]);//比较输入值和已有密码
- }
- }
- i=0; //计数器复位
- if(Flag)//如果比较全部相同,标志位置1
- {
- pass();
- display_GB2312_string(5,1," ");//清除该行
- TR0=1;
- RELAY=0;
- error=0;//输入正确则次数清零,重新计数
- Flag=0; //清除正确标志
- shoudongshuru_flag=1;
- return 0;
- }
- else
- {
- display_GB2312_string(5,1," ");//清除该行
- display_GB2312_string(5,1,"Wrong! Retry! ");//密码错误,提示重新输入
- error++;//连续输入错误,则次数累加
- if(error==3)
- {
- error=0;
- lcd_clear();
- display_GB2312_string(5,1,"禁止入内 ");//密码错误,提示重新输入
- delayms(1500);
- shoudongshuru_flag=0;
- return 1;
- }
- }
- }
- if(key2=='B') //授权修改用户密码
- {
- shouquan_flag=1;
- lcd_clear();
- while(administer()) //管理员返回0,密码正确shouquan_flag=0
- {
- if(KeyPro()=='A')
- {
- shoudongshuru_flag=0;
- return 1;
- }
- }
- if(shouquan_flag==0)display_GB2312_string(1,1," 请输入新密码 ");//管理员密码正确后的提示
- if(shouquan_flag==1)//管理员密码错误,或退出管理员时的提示
- {
- display_GB2312_string(1,1," 请输入密码 ");
- display_GB2312_string(3,1,"或按B授权改密码 ");
- }
- num=0;//输入次数计数清零
- n=0; //输入密码长度计数清零
- while(shouquan_flag==0)//管理员密码正确进入密码修改
- {
- key2=KeyPro();
- if(key2=='A')return 1;
- if(key2!=0xff)
- {
- if(n==0&&num==0)//第一次输入并且是第一位密码
- {
- display_GB2312_string(1,1," 请输入新密码 ");
- display_GB2312_string(3,1," ");
- }
- if((n<16)&&(key2<=9))//按键为1-9 且密码长度小于16位
- {
- passwordtemp[n]=key2;
- Sent_Byte(key2);
- display_GB2312_string(3,n*8+1,&asteris);//输入的密码用"*"代替
- n++; //输入数值累加
- }
- if('*'==key2&&n>0)//清除、后退一位
- {
- n--;
- for(k=n;k<16;k++)
- display_GB2312_string(3,k*8,&spacin);//输入用空格代替
- }
- if(('D'==key2)||(n==16))//输入按键值D或者密码输入到最大值16,表示输入结束,需要进行比对
- {
- if(num==0) //第一次输入密码
- {
- passwordlength=n; //计算输入密码长度
- for(n=0;n<passwordlength;n++)//暂时存储
- {
- passwordlast[n]=passwordtemp[n];//转存密码
- passwordtemp[n]=0;//清空当前
- }
- n=0;//计数器复位
- display_GB2312_string(1,1," 请再次输入密码 ");
- display_GB2312_string(3,1," ");//清除
- num++;
- }
- else if(passwordlength==n&&num==1)//第二次输入密码 长度相等则比较,否则直接输出错误
- {
- Flag=1;//先把比较位置1
- for(j=0;j<passwordlength;j++)//循环比较数值,如果有一个不等 则最终Flag值为0
- Flag=Flag&&(passwordlast[j]==passwordtemp[j]);//比较上次输入值和现在密码是否一样
- if(Flag==1)
- {
- //pass();
- num=0;
- shouquan_flag=0;
- IapEraseSector(IAP_ADDRESS1); //清除
- delayms(10);
- IapProgramByte(IAP_ADDRESS1,n);//写入密码个数
- for(n=1;n<=passwordlength;n++)//存储
- {
- IapProgramByte(IAP_ADDRESS1+n,passwordtemp[n-1]);//写入密码
- Sent_Byte(passwordtemp[n-1]);
- }
- delayms(10);
- User_len=IapReadByte(IAP_ADDRESS1);//读取密码个数
- Sent_Byte(User_len);
- for(n=1;n<=User_len;n++)
- {
- Userpassword[n-1]=IapReadByte(IAP_ADDRESS1+n); //读取 密码
- Sent_Byte(Userpassword[n-1]);
- }
- n=0;
- display_GB2312_string(1,1," 修改密码成功 ");
- delayms(1500);
- num=0;
- return 0;
- }
- else if(Flag==0)
- {
- display_GB2312_string(3,1," 请重新输入 ");//清除
- display_GB2312_string(1,1," 两次输入不同 ");//清除该行
- num=0;
- n=0;
- error++;//连续输入错误,则次数累加
- if(error==3)
- {
- display_GB2312_string(3,1," ");//清除
- display_GB2312_string(1,1,"错误3次,修改失败");//密码错误,返回界面
- delayms(1500);
- shouquan_flag=1;
- return 1;
- //while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
- }
- }
- }
- else if(num==1)
- {
- display_GB2312_string(3,1," 请重新输入 ");//清除
- display_GB2312_string(1,1," 两次输入不同 ");//清除该行
- num=0;
- n=0;
- error++;//连续输入错误,则次数累加
- if(error==3)
- {
- display_GB2312_string(3,1," ");//清除
- display_GB2312_string(1,1,"错误3次,修改失败");//密码错误,返回界面
- delayms(1500);
- shouquan_flag=1;
- return 1;
- //while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /****************************************************
- 函数名称:Timer0Init(void)
- 入口参数:无
- 出口参数:无
- 功能: 用于定时关闭门
- 调用函数:无
- ****************************************************/
- void Timer0Init(void) //50毫秒@11.0592MHz
- {
- AUXR &= 0x7F; //定时器时钟12T模式
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x00; //设置定时初值
- TH0 = 0x4C; //设置定时初值
- TF0 = 0; //清除TF0标志
- ET0 = 1; //允许定时器0中断
- TR0 = 0; //定时器0开始计时
- }
- void Timer1Init(void) //50毫秒@11.0592MHz
- {
- AUXR &= 0xBF; //定时器时钟12T模式
- TMOD &= 0x0F; //设置定时器模式
- TMOD |= 0x10; //设置定时器模式
- TL1 = 0x00; //设置定时初值
- TH1 = 0x4C; //设置定时初值
- TF1 = 0; //清除TF1标志
- ET1 = 1; //允许定时器0中断
- TR1 = 0; //定时器1开始计时
- }
- /****************************************************
- 函数名称:主函数
- ****************************************************/
- main()
- {
- uchar key,j=0,k=0,n,i,sel=0;
- unsigned long int display_data=0;
- BELL=0;//关闭
- RELAY=1;
- io_init();//初始化引脚
- UART_Init();//初始化UART通讯
- rom_cs=1;
- lcd_init();//初始化液晶屏
- init_spi();//初始化SPI通讯
- Timer0Init();//初始化定时器0关门用
- Timer1Init();//初始化定时器1时钟闪烁用
- Ds1302_Init();
- EA =1; //单片机中断允许
- //IapEraseSector(IAP_ADDRESS);//清除数据 卡数据
- //IapEraseSector(IAP_ADDRESS1);//清除数据 用户密码
- for(j=0;j<5;j++)//5行
- for(k=0;k<5;k++)//4列
- IC_EEPROM[j][k]=IapReadByte(IAP_ADDRESS+j*5+k);//读出卡数据
- for(j=0;j<5;j++)
- if(IC_EEPROM[j][4]!=0xff) IC_NUM=IC_EEPROM[j][4];//读出卡刷入顺序
- User_len=IapReadByte(IAP_ADDRESS1);//读取用户密码个数
- //Sent_Byte(User_len);
- if(User_len==0xff)User_len=6;//初始化用户密码长度6位
- //Sent_Byte(User_len);
- for(k=1;k<=User_len;k++) //读取用户密码
- {
- i=IapReadByte(IAP_ADDRESS1+k); //读取用户密码
- if(i==0xff)Userpassword[k-1]=0;//初始话用户密码为000000
- else Userpassword[k-1]=i;
- }
- // for(j=0;j<6;j++)Sent_Byte(Userpassword[j]);
- PcdReset(); //初始化射频芯片
- PcdAntennaOff();
- PcdAntennaOn();
- delayms(100);
- PcdReset();//复位芯片,打开天线
- PcdAntennaOff();
- PcdAntennaOn();
- //M500PcdConfigISOType( 'A' );//设置RC632的工作方式
- //Delay_ms(100);
- lcd_clear();
- while(1)
- {
- key=KeyPro();//按键检测
- if(key!=0xff)
- {
- IC:if(key=='#')shudongshuru(key);//手动输入密码
- if(key=='C')zhuxiao_one(key);//注销单张卡 持卡注销
- if(key=='*')zhuxiao_all(key);//注销所有卡
- if(key=='B')shouquan(key);//授权卡
- IC_flag=0;
- lcd_clear();
- }
- Auto_Reader();
- if(IC_flag==1)//刷卡标记
- {
- display_GB2312_string(1,1," 欢迎光临 ! ");
- IC_flag=0;
- //for(n=0;n<4;n++)Sent_Byte(ICCODE[n]);
- for(j=0;j<5;j++)//5行
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
代码.rar
(197.69 KB, 下载次数: 516)
|