基于单片机的IC卡读写 - 图文
更新时间:2024-05-28 19:30:02 阅读量: 综合文库 文档下载
基于单片机的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 \#include \#include \#include
#include \#include \
#define uchar unsigned char #define uint unsigned int
sbit Speak = P2^7;//蜂鸣器 sbit RED = P3^4; //红色指示灯 sbit GREEN = P3^3;//绿色指示灯 sbit Relay = P3^2; //继电器
sbit KEY1 = P1^3;//小时加按键 sbit KEY2 = P1^4; //小时减按键 sbit KEY3 = P1^5; //分钟加按键 sbit KEY4 = P1^6; //分钟减按键 sbit KEY5 = P1^7; //添加删除卡
sbit KEY = P2^6; //开门
unsigned char idata RevBuffer[30]; unsigned char Card_Num; void iccardcode(); //系统初始化
void InitializeSystem()//IC卡初始化 {
PcdReset(); //IC卡初始化
PcdAntennaOff(); //IC卡初始化 PcdAntennaOn(); //IC卡初始化
M500PcdConfigISOType( 'A' );//IC卡初始化 }
unsigned char idata UID[4],Temp[4];//读取卡号数组 unsigned char Table[3];//显示数组 unsigned char Num; unsigned Count,Countf,Count1,Count2,Count3,Count4,Count5,C_flag;//卡序号void Auto_Reader(void) //自动寻卡 {
if(PcdRequest(0x52,Temp)==0) //找到卡 {
if(PcdAnticoll(UID)==0) {
char Speak=0;delay_10ms(20);Speak=1;//蜂鸣器提示
Table[0]=UID[0]/100+0x30; //卡号显示 Table[1]=UID[0]/10+0x30; //卡号显示 Table[2]=UID[0]+0x30; //卡号显示
LCD1602_Disp_ZF(0x80+0x40,\卡号显示
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,\卡有效
GREEN = 0;Relay=0;delay_10ms(200);Relay=1;GREEN = 1; //绿灯亮,打开继电器
C_flag=1; } else {
LCD1602_Disp_ZF(0x88+0x40,\卡无效 RED = 0;delay_10ms(500);RED = 1; //红灯亮 C_flag=2; }
delay_10ms(200); LCD1602_Disp_ZF(0x80+0x40,\Swipecard\显示初始界面
} } }
uchar DS1302_Table[7]={0}; //读取时间值
void Display_LCD2(uchar Dis_Hour,uchar Dis_Min,uchar Dis_Sec)//显示时间值 {
uchar Dis_Table[8]=\
Dis_Table[0] = Dis_Hour/10+0x30; Dis_Table[1] = Dis_Hour+0x30;
Dis_Table[3] = Dis_Min/10+0x30; Dis_Table[4] = Dis_Min+0x30;
Dis_Table[6] = Dis_Sec/10+0x30;
Dis_Table[7] = Dis_Sec+0x30;
LCD1602_Disp_ZF(0x85,Dis_Table,8);//显示时间值 }
void Run_DS1302(void) {
uchar sec, 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]);//显示时间值 }
void main(void) {
InitializeSystem(); LCD1602_init();
//Money_1=x24c02_read(0X01); //x24c02_write(0X03,Money_3); LCD1602_Disp_ZF(0x80,\
//0123456789abcdef
LCD1602_Disp_ZF(0x80+0x40,\
//LCD1602_Disp_ZF(0x80+0x40,\
//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,\卡有效
GREEN = 0;Relay=0;delay_10ms(200);Relay=1;GREEN = 1; //绿灯亮,打开继电器
delay_10ms(200); LCD1602_Disp_ZF(0x80+0x40,\Swipecard\显示初始界面 }
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,\ 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,\ 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,\
C_flag =0; while(!KEY5); } }
////////////////////// } }
void iccardcode() {
unsigned char cmd; unsigned char status;
cmd = RevBuffer[0]; switch(cmd) {
case 1: // Halt the card //终止卡的操作 status= PcdHalt();; RevBuffer[0]=1;
RevBuffer[1]=status; break;
case 2: // Request,Anticoll,Select,return CardType(2 bytes)+CardSerialNo(4 bytes)
// 寻卡,防冲突,选择卡 返回卡类型(2 bytes)+ 卡系列号(4 bytes)
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;
case 3: // 防冲突 读卡的系列号 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;
case 4: // 选择卡 Select Card //status=PcdSelect(MLastSelectedSnr); if(status!=MI_OK) {
RevBuffer[0]=1; RevBuffer[1]=status; break; }
RevBuffer[0]=3;
RevBuffer[1]=status; break;
case 5: // Key loading into the MF RC500's EEPROM
//status = PcdAuthState(RevBuffer[1], RevBuffer[3], DefaultKey, MLastSelectedSnr);// 校验卡密码 RevBuffer[0]=1;
RevBuffer[1]=status; break; case 6:
RevBuffer[0]=1;
RevBuffer[1]=status; break; case 7:
RevBuffer[0]=1;
RevBuffer[1]=status; break;
case 8: // Read the mifare card // 读卡
status=PcdRead(RevBuffer[1],&RevBuffer[2]); if(status==0)
{RevBuffer[0]=17;} else
{RevBuffer[0]=1;}
RevBuffer[1]=status; break;
case 9: // Write the mifare card // 写卡 下载密码
status=PcdWrite(RevBuffer[1],&RevBuffer[2]); RevBuffer[0]=1;
RevBuffer[1]=status; break; case 10:
PcdValue(RevBuffer[1],RevBuffer[2],&RevBuffer[3]); RevBuffer[0]=1; RevBuffer[1]=status; break;
case 12: // 参数设置
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 \#include \#include \#include \#include \#include \#include \#include \#include \#include \void init_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; }
void main(void) {INT8U key;
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--; else states=0;
if(key==13) if(++states>3) states=3; ctrl_process(); }} #include
#define uchar unsigned char #define uint unsigned int
#define LCD_data P0 //数据口
sbit LCD_RS = P2^2; //寄存器选择输入 sbit LCD_RW = P2^1; //液晶读/写控制 sbit LCD_EN = P2^0; //液晶使能控
uchar code dis0[]=\卡读写系统 %uchar code dis1[]=\卡输入 %uchar code dis2[]=\密码输入:8位 %uchar code dis3[]=\卡登记 %uchar code dis4[]=\密码设置:8位 %uchar code dis5[]=\成功 %uchar code dis6[]=\失败 %uchar code dis7[]=\桂林电子科技大学%uchar code dis8[]=\控制工程 \
uchar code dis9[]=\接口实验 \ uchar code dis10[]=\司亚 \void delay(int ms) //延时xms {while(ms--) { uchar i;
for(i=0;i<250;i++)
{_nop_();_nop_();_nop_();_nop_();}}} void delayNOP() //延时4us
{ _nop_(); _nop_(); _nop_(); _nop_();} bit lcd_busy()
{ bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP();
result = (bit)(LCD_data&0x80); LCD_EN = 0;
return(result); }
void write_cmd(uchar cmd) { unsigned int K=20000;
while(lcd_busy() && K--); //预防没插LCD时候停在这 LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_();
LCD_data = cmd; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; }
void lcd_wdat(uchar dat) { unsigned int K=20000;
while(lcd_busy() && K--); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; LCD_data= dat; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; } void lcd_init()
{ write_cmd(0x36); delay(5);
write_cmd(0x30); delay(5);
write_cmd(0x0C); delay(5);
write_cmd(0x01); delay(5);}
void lcd_pos(uchar X,uchar Y) {uchar pos; if (X==0) {X=0x80;} else if (X==1) {X=0x90;} else if (X==2) {X=0x88;} else if (X==3) {X=0x98;} pos = X+Y ; write_cmd(pos);} void display_all() {uchar i;
lcd_pos(0,0); // i = 0;
while(dis0[i] != '\\0')
{lcd_wdat(dis0[i]); // i++; }
lcd_pos(1,0); // i = 0;
while(dis1[i] != '\\0')
{ lcd_wdat(dis1[i]); // i++;}
lcd_pos(2,0); // i = 0;
第一行显示数字0~9 显示字母 第二行显示字母 显示字母 第三行显示文字 while(dis2[i] != '\\0') {lcd_wdat(dis2[i]); i++;}
lcd_pos(3,0); //第四行显示广工无线电社 i = 0;
while(dis3[i] != '\\0') {
lcd_wdat(dis3[i]); i++; }}
void display(uchar a,uchar b,uchar c) {uchar i;
lcd_pos(a,b); i = 0; switch(c)
{case 0: while(dis0[i] != '\\0') {lcd_wdat(dis0[i]); i++; } break;
case 1:while(dis1[i] != '\\0')
{lcd_wdat(dis1[i]);i++;}break; case 2:
while(dis2[i] != '\\0') {lcd_wdat(dis2[i]); i++; }break;
case 3: while(dis3[i] != '\\0') {lcd_wdat(dis3[i]);i++; } break;
case 4: while(dis4[i] != '\\0')
{lcd_wdat(dis4[i]); i++;}break;
case 5: while(dis5[i] != '\\0')
{lcd_wdat(dis5[i]); i++;} break; case 6: while(dis6[i] != '\\0')
{lcd_wdat(dis6[i]); i++;} break; case 7: while(dis7[i] != '\\0')
{lcd_wdat(dis7[i]); i++;} break; case 8: while(dis8[i] != '\\0')
{lcd_wdat(dis8[i]); i++;} break; case 9: while(dis9[i] != '\\0')
{lcd_wdat(dis9[i]); i++;} break;
case 10: while(dis10[i] != '\\0')
{ lcd_wdat(dis10[i]); i++;} break; default :break; } }
void display2(uchar a,uchar b,uchar *p,uchar num) { uchar i;
lcd_pos(a,b);
for(i=0;i lcd_wdat(p[i]); } void display_clear_line(uchar a) { uchar i; lcd_pos(a,0); for(i=0;i<16;i++) lcd_wdat(' '); } 4.实物验证结果如图7所示: 图7:实物验证结果 实物验证可以实现IC卡的读写加密,使用LCD12864中文字幕可以更方便读取信息,对实物验证程序进行了略微的修改,第一次买的射频模块是坏的浪费了太多时间。换了新板子,最终能达到要求。 心得体会: 通过本次的实验,小组成员都发现自己的知识面还是非常的狭窄,缺少的东 西也有很多,在网上查找一些相关的资料以及在图书馆借阅了几本关于单片机方面的书籍,慢慢的懂了一些关于编程和仿真方面的问题。通过这次实验,成员们都发现各自还是存在一些问题。这些不经意的东西虽然看起来不起眼,但是在试验中是不可忽视的问题。这次试验,硬件调试让我遇到的困难有很多,例如一开始在编程的时候,IC卡在射频模块上无法读取以及上位机无法显示,失败之后吸取经验最终在同学帮助下实现了读写。这次的实验,学习到的内容也有很多,不求在一个试验中就能让我学到很多的东西,但在以后的学习中,会慢慢的一点点改进,熟练的理解以及掌握相关的知识,希望能在这方面学到的越来越多。
正在阅读:
基于单片机的IC卡读写 - 图文05-28
梁启超论《史记》的读法11-30
感谢老师的散文02-06
音乐课听课记录及评课07-30
关于加强干部作风建设的调研报告04-18
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 单片机
- 读写
- 基于
- 图文
- 思想政治教育专业毕业论文 - 图文
- 同步习题库
- 19第二节工程计量--2015年监理工程师-中业网校投资控制讲义
- 教师风采简介范例
- 苏教版六年级语文上册一课一练(整理)
- 嵌入式SQL语言imp
- 毕业论文 心率监测系统设计
- 中国护眼仪行业市场前景分析预测报告(目录)
- CP和CPK介绍
- (泰山版2015)小学二年级下册《综合实践活动
- 植物多靶点CRISPR-Cas9载体使用方法(2015-5-1)
- 《空气占据空间吗》教学设计
- 东北三省三校(哈师大附中、东北师大附中、辽宁省实验中学)2018届
- 电力系统分析 第三章例题
- 鲁教版九年级思想品德导学案全册
- 中景石化压力容器延期监检说明函2017.11.21修改版
- 备考2015年全国会计从业资格考试 财经法规与职业道德 必背多选10
- 刘仁达等诉唐小军建设工程施工合同纠纷案
- 信息管理概论复习题
- 南宁沛鸿民族中学年高一下学期数学期中考试