基于单片机的IC卡读写.docx
《基于单片机的IC卡读写.docx》由会员分享,可在线阅读,更多相关《基于单片机的IC卡读写.docx(25页珍藏版)》请在冰豆网上搜索。
基于单片机的IC卡读写
基于单片机的IC卡读写系统
实验目的:
1.学会并掌握可keil软件的使用;
2.学会并掌握protues软件的使用;
3.实现基于单片机的IC卡读写;
4.通过实验巩固单片机相关知识和检验自身动手能力
实验要求:
掌握单片机相关知识.利用单片机控制和射频模块组合来读写IC卡.并实现软硬件的仿真模拟。
lC卡读卡器以MCS-51系列单片机作为核心构成.主要用于家庭和机构门锁的开关.具有安全稳定的特点.在识别.删除.添加.自动开锁时.用于对IC卡进行读写操作。
实验设备和仪器:
1.89c51单片机最小系统
2.射频模块RC522.智能IC卡以及其他附加电路
实验内容:
本次实验设计是由小组五个成员共同完成基于单片机的IC卡读写系统并完成实物搭建和撰写实验报告。
方案一:
实验步骤:
1.利用protues画电路图.电路图如图1所示:
图1:
方案一电路图
2.模拟刷卡后显示.如图二:
图2:
方案一实现图
3.根据电路图编写C语言代码:
代码如下:
#include"reg52.h"
#include"main.h"
#include"mfrc522.h"
#include
#include"LCD1602.h"
#include"DS1302.h"
#defineucharunsignedchar
#defineuintunsignedint
sbitSpeak=P2^7;//蜂鸣器
sbitRED=P3^4;//红色指示灯
sbitGREEN=P3^3;//绿色指示灯
sbitRelay=P3^2;//继电器
sbitKEY1=P1^3;//小时加按键
sbitKEY2=P1^4;//小时减按键
sbitKEY3=P1^5;//分钟加按键
sbitKEY4=P1^6;//分钟减按键
sbitKEY5=P1^7;//添加删除卡
sbitKEY=P2^6;//开门
unsignedcharidataRevBuffer[30];
unsignedcharCard_Num;
voidiccardcode();
//系统初始化
voidInitializeSystem()//IC卡初始化
{
PcdReset();//IC卡初始化
PcdAntennaOff();//IC卡初始化
PcdAntennaOn();//IC卡初始化
M500PcdConfigISOType('A');//IC卡初始化
}
unsignedcharidataUID[4],Temp[4];//读取卡号数组
unsignedcharTable[3];//显示数组
unsignedcharNum;
unsignedcharCount,Countf,Count1,Count2,Count3,Count4,Count5,C_flag;//卡序号
voidAuto_Reader(void)//自动寻卡
{
if(PcdRequest(0x52,Temp)==0)//找到卡
{
if(PcdAnticoll(UID)==0)
{
Speak=0;delay_10ms(20);Speak=1;//蜂鸣器提示
Table[0]=UID[0]/100+0x30;//卡号显示
Table[1]=UID[0]/10%10+0x30;//卡号显示
Table[2]=UID[0]%10+0x30;//卡号显示
LCD1602_Disp_ZF(0x80+0x40,"Num:
",16);//卡号显示
LCD1602_Disp_ZF(0x84+0x40,Table,3);//卡号显示
Count=UID[0];//判断卡是不是有效
if((Count==Count1)||(Count==Count2)||(Count==Count3)||(Count==Count4)||(Count==Count5))
{
LCD1602_Disp_ZF(0x88+0x40,"Welcome",7);//卡有效
GREEN=0;Relay=0;delay_10ms(200);Relay=1;GREEN=1;//绿灯亮.打开继电器
C_flag=1;
}
else
{
LCD1602_Disp_ZF(0x88+0x40,"Error",7);//卡无效
RED=0;delay_10ms(500);RED=1;//红灯亮
C_flag=2;
}
delay_10ms(200);
LCD1602_Disp_ZF(0x80+0x40,"PleaseSwipecard",16);//显示初始界面
}
}
}
ucharDS1302_Table[7]={0};//读取时间值
voidDisplay_LCD2(ucharDis_Hour,ucharDis_Min,ucharDis_Sec)//显示时间值
{
ucharDis_Table[8]="11:
22:
33";
Dis_Table[0]=Dis_Hour/10+0x30;
Dis_Table[1]=Dis_Hour%10+0x30;
Dis_Table[3]=Dis_Min/10+0x30;
Dis_Table[4]=Dis_Min%10+0x30;
Dis_Table[6]=Dis_Sec/10+0x30;
Dis_Table[7]=Dis_Sec%10+0x30;
LCD1602_Disp_ZF(0x85,Dis_Table,8);//显示时间值
}
voidRun_DS1302(void)
{
ucharsec,min,hour,day,month,week,year;
v_W1302(0x8f,0);
sec=bcdtodec(uc_R1302(0x81));//读出DS1302中的秒
v_W1302(0x8f,0);
min=bcdtodec(uc_R1302(0x83));//读出DS1302中的分
v_W1302(0x8f,0);
hour=bcdtodec(uc_R1302(0x85));//读出DS1302中的小时
v_W1302(0x8f,0);
day=bcdtodec(uc_R1302(0x87));//读出DS1302中的日
v_W1302(0x8f,0);
month=bcdtodec(uc_R1302(0x89));//读出DS1302中的月
v_W1302(0x8f,0);
week=bcdtodec(uc_R1302(0x8b));//读出DS1302中的星期
v_W1302(0x8f,0);
year=bcdtodec(uc_R1302(0x8d));//读出DS1302中的年
DS1302_Table[0]=year;
DS1302_Table[1]=month;
DS1302_Table[2]=day;
DS1302_Table[3]=week;
DS1302_Table[4]=hour;
DS1302_Table[5]=min;
DS1302_Table[6]=sec;
Display_LCD2(DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//显示时间值
}
voidmain(void)
{
InitializeSystem();
LCD1602_init();
//Money_1=x24c02_read(0X01);
//x24c02_write(0X03,Money_3);
LCD1602_Disp_ZF(0x80,"Time:
",5);
//0123456789abcdef
LCD1602_Disp_ZF(0x80+0x40,"PleaseSwipecard",16);
//LCD1602_Disp_ZF(0x80+0x40,"Num:
",4);
//ISP_ERASE(0x2c00);//注意:
字节编程时必须要先要擦除整个扇区
//for(i=0;i<255;i++)
//ISP_PROGRAM(0x2c00+i,0x00);
while
(1)
{
//////////////////////////
if(!
KEY)
{
Speak=0;delay_10ms(20);Speak=1;//蜂鸣器提示
LCD1602_Disp_ZF(0x88+0x40,"Welcome",7);//卡有效
GREEN=0;Relay=0;delay_10ms(200);Relay=1;GREEN=1;//绿灯亮.打开继电器
delay_10ms(200);
LCD1602_Disp_ZF(0x80+0x40,"PleaseSwipecard",16);//显示初始界面
}
Run_DS1302();//时间显示
//delay_10ms(200);
if(!
KEY1)//调节小时加
{
delay_10ms(50);
if(!
KEY1)//调节小时加
{
DS1302_Table[4]++;//调节小时加
Write_DS1302Init(0,0,0,0,DS1302_Table[4],DS1302_Table[5],0);//调节小时加
}
}
if(!
KEY2)//调节小时减
{
delay_10ms(50);
if(!
KEY2)//调节小时减
{//调节小时减
DS1302_Table[4]--;//调节小时减
Write_DS1302Init(0,0,0,0,DS1302_Table[4],DS1302_Table[5],0);//调节小时减
}
}
//////////////////////////////////
if(!
KEY3)//调节分钟加
{
delay_10ms(50);//调节分钟加
if(!
KEY3)
{
DS1302_Table[5]++;//调节分钟加
Write_DS1302Init(0,0,0,0,DS1302_Table[4],DS1302_Table[5],0);//调节分钟加
}
}
if(!
KEY4)//调节分钟减
{
delay_10ms(50);//调节分钟减
if(!
KEY4)//调节分钟减
{
DS1302_Table[5]--;//调节分钟减
Write_DS1302Init(0,0,0,0,DS1302_Table[4],DS1302_Table[5],0);//调节分钟减
}
}
if(!
KEY5)//添加删除卡
{
delay_10ms(50);
if(!
KEY5)//添加删除卡
{
if(C_flag==2)//添加卡
{
//0123456789abcdef
LCD1602_Disp_ZF(0x80+0x40,"RegisterCard!
",16);
Countf++;
if(Countf==6)Countf=1;
if(Countf==1)Count1=Count;//记忆卡号
if(Countf==2)Count2=Count;//记忆卡号
if(Countf==3)Count3=Count;//记忆卡号
if(Countf==4)Count4=Count;//记忆卡号
if(Countf==5)Count5=Count;//记忆卡号
}
if(C_flag==1)//删除卡
{
//0123456789abcdef
LCD1602_Disp_ZF(0x80+0x40,"CleanCard!
",16);
if(Count==Count1)Count1=0;//删除卡号
if(Count==Count2)Count2=0;//删除卡号
if(Count==Count3)Count3=0;//删除卡号
if(Count==Count4)Count4=0;//删除卡号
if(Count==Count5)Count5=0;//删除卡号
}
Speak=0;delay_10ms(200);Speak=1;
LCD1602_Disp_ZF(0x80+0x40,"PleaseSwipecard",16);
C_flag=0;
while(!
KEY5);
}
}
//////////////////////
}
}
voidiccardcode()
{
unsignedcharcmd;
unsignedcharstatus;
cmd=RevBuffer[0];
switch(cmd)
{
case1:
//Haltthecard//终止卡的操作
status=PcdHalt();;
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case2:
//Request,Anticoll,Select,returnCardType(2bytes)+CardSerialNo(4bytes)
//寻卡.防冲突.选择卡返回卡类型(2bytes)+卡系列号(4bytes)
status=PcdRequest(RevBuffer[1],&RevBuffer[2]);
if(status!
=0)
{
status=PcdRequest(RevBuffer[1],&RevBuffer[2]);
if(status!
=0)
{
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
}
}
RevBuffer[0]=3;
RevBuffer[1]=status;
break;
case3:
//防冲突读卡的系列号MLastSelectedSnr
status=PcdAnticoll(&RevBuffer[2]);
if(status!
=0)
{
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
}
//memcpy(MLastSelectedSnr,&RevBuffer[2],4);
RevBuffer[0]=5;
RevBuffer[1]=status;
break;
case4:
//选择卡SelectCard
//status=PcdSelect(MLastSelectedSnr);
if(status!
=MI_OK)
{
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
}
RevBuffer[0]=3;
RevBuffer[1]=status;
break;
case5:
//KeyloadingintotheMFRC500'sEEPROM
//status=PcdAuthState(RevBuffer[1],RevBuffer[3],DefaultKey,MLastSelectedSnr);//校验卡密码
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case6:
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case7:
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case8:
//Readthemifarecard
//读卡
status=PcdRead(RevBuffer[1],&RevBuffer[2]);
if(status==0)
{RevBuffer[0]=17;}
else
{RevBuffer[0]=1;}
RevBuffer[1]=status;
break;
case9:
//Writethemifarecard
//写卡下载密码
status=PcdWrite(RevBuffer[1],&RevBuffer[2]);
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case10:
PcdValue(RevBuffer[1],RevBuffer[2],&RevBuffer[3]);
RevBuffer[0]=1;
RevBuffer[1]=status;
break;
case12:
//参数设置
PcdBakValue(RevBuffer[1],RevBuffer[2]);
RevBuffer[0]=1;//contact
RevBuffer[1]=0;
break;
}
}
4.实物验证结果如图4所示:
图4:
实物验证结果
实物验证可以实现IC卡的读写.由于每个开发板不同.相比仿真程序.对实物验证程序进行了略微的修改.最小系统的LCD1602口不能使用使用外接杜邦线.为了稳定最终选择重新字节焊接板子.最终能达到要求。
方案二:
实验步骤:
1.电路图如图5所示:
图5:
方案一电路图
2.刷卡前后显示以及操作.如下图6:
图6:
方案一实现图
3.根据电路图编写C语言部分主要代码:
代码如下:
#include"reg52.h"
#include"main.h"
#include"uart.h"
#include"timer.h"
#include"rc522.h"
#include"ctrl.h"
#include"lcd12864.h"
#include"beep.h"
#include"key.h"
#include"EEPROM.h"
voidinit_all(void)
{EA=0;
PT1=1;
init_timer();
Serial_init();
init_rc522();
lcd_init();
EEPROM_READ(0,Card_SN_BUF,4);
EEPROM_READ(1,Card_SN_BUF1,4);
EEPROM_READ(2,Card_SN_BUF2,4);
EEPROM_READ(3,Card_SN_BUF3,4);
EEPROM_READ(4,Card_SN_BUF4,4);
EEPROM_READ(5,Card_SN_BUF5,4);
EEPROM_READ(6,Card_NUM_BUF,1);
EEPROM_READ(7,KEY_BUF,8);
EA=1;
}
voidmain(void)
{INT8Ukey;
relay_OFF();
Delay_ms(500);
init_all();
LED_BLINK_1();
display(0,0,7);
display(1,0,8);
display(2,0,9);
display(3,0,10);
Delay_ms(500);
Delay_ms(500);
Delay_ms(500);
Delay_ms(500);
Delay_ms(500);
display_clear_line(0);
display_clear_line
(1);
display_clear_line
(2);
display_clear_line(3);
display(0,0,0);
while
(1)
{key=key_scan();
if(key==12)if(states>0)states--;
elsestates=0;
if(key==13)if(++states>3)states=3;
ctrl_process();}}
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLCD_dataP0//数据口
sbitLCD_RS=P2^2;//寄存器选择输入
sbitLCD_RW=P2^1;//液晶读/写控制
sbitLCD_EN=P2^0;//液晶使能控
ucharcodedis0[]="IC卡读写系统";
ucharcodedis1[]="1.IC卡输入";
ucharcodedis2[]="2.密码输入:
8位";
ucharcodedis3[]="3.IC卡登记";
ucharcodedis4[]="4.密码设置:
8位";
ucharcodedis5[]="成功";
ucharcodedis6[]="失败";
ucharcodedis7[]="桂林电子科技大学";
ucharcodedis8[]="控制工程";
ucharcodedis9[]="接口实验";
ucharcodedis10[]="MADEBY:
司亚";
voiddelay(