RFID RC522智能钱包
基于51单片机的RFID RC522智能钱包,这个程序主要演示的是RFID RC522智能钱包中的设置及扣款功能,相信会扣款那么充值也就改一个数字的事,具体的功能要自己根据实际情况进行编写,下面是代码:
#include "reg52.h"
#include "main.h"
#include "mfrc522.h"
#include
//M1卡的某一块写为如下格式,则该块为钱包,可接收扣款和充值命令
//4字节金额(低字节在前)+4字节金额取反+4字节金额+1字节块地址+1字节块地址取反+1字节块地址+1字节块地址取反
unsigned char code data2[4] = {0x01,0,0,0};
unsigned char code DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char g_ucTempbuf[20];
unsigned char idata MLastSelectedSnr[4];
unsigned char idata RevBuffer[30];
//unsigned char data IDBuffer[20];
void ID_Verify();
void delay_ms(unsigned int ms);
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;
}
}
/////////////////////////////////////////////////////////////////////
//系统初始化
/////////////////////////////////////////////////////////////////////
void InitializeSystem()
{
P0 = 0xFF; P1 = 0xFF; P3 = 0xFF;
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数
LED_GREEN = 1;
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
LED_GREEN = 0;
delay_10ms(10);
LED_GREEN = 1;
delay_10ms(10);
LED_GREEN = 0;
}
///////////////////////////////////////////////////////////////////////
// 接收和发送中断
///////////////////////////////////////////////////////////////////////
void isr_UART(void) interrupt 4 using 1
{
unsigned char len, i;
if(TI)
{
TI=0;
len=RevBuffer[0];
for(i=0;i0;m--)
for(n=110;n>0;n--);
}
void ID_Verify()
{
while(1)
{
//寻卡
RevBuffer[0]=2;
RevBuffer[1]=0x52;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
//防冲突
RevBuffer[0]=0x03;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
//选择卡
RevBuffer[0]=0x04;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
//密码检验
RevBuffer[0]=0x05;
RevBuffer[1]=0x61;
RevBuffer[3]=0x08;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
//读09块的16个字节数据
RevBuffer[0]=0x08;
RevBuffer[1]=0x09;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
TI=1;
//扣款
RevBuffer[0]=0x0A;//cmd
RevBuffer[1]=0xC0;//扣款
RevBuffer[2]=0x09;//地址09块
RevBuffer[3]= data2[0];
RevBuffer[4]= data2[1];
RevBuffer[5]= data2[2];
RevBuffer[6]= data2[3];
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
//读09块的16个字节数据
RevBuffer[0]=0x08;
RevBuffer[1]=0x09;
iccardcode();
if(RevBuffer[1]!=0)
{
continue;
}
if(RevBuffer[1]==0)
{
LED_SWITCH=0;
delay_ms(1000);
LED_SWITCH=1;
}
TI=1;
}
}
//////////////////////////////////
//端口定义
/////////////////////////////////////////////////////////////////////
//MFRC522
sbit MF522_RST = P1^4; //RC500片选
sbit MF522_NSS = P1^0;
sbit MF522_SCK = P1^1;
sbit MF522_SI = P1^2;
sbit MF522_SO = P1^3;
//指示灯
sbit LED_GREEN = P1^5;
sbit LED_SWITCH = P1^6;
/////////////////////////////////////////////////////////////////////
//函数原型
/////////////////////////////////////////////////////////////////////
void InitializeSystem();
#define BAUD_115200 256 - (OSC_FREQ/192L)/115200L // 255
#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L // 254
#define BAUD_38400 256 - (OSC_FREQ/192L)/38400L // 253
#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L // 252
#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L // 250
#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L // 248
#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L // 244
#define OSC_FREQ 22118400L
//#define OSC_FREQ 7372800L
#define OSC_FREQ 22118400L
#define RCAP2_50us 65536L - OSC_FREQ/40417L
#define RCAP2_1ms 65536L - OSC_FREQ/2000L
#define RCAP2_10ms 65536L - OSC_FREQ/1200L
#define TIME0_500us 65536L - OSC_FREQ/8000L
#define TIME0_10ms 65536L - OSC_FREQ/200
#define CALL_isr_UART() TI = 1
#define TRUE 1
#define FALSE 0
#include
#include "reg52.h"
#include "main.h"
#include "mfrc522.h"
#include
#define MAXRLEN 18
/////////////////////////////////////////////////////////////////////
//功 能:寻卡
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
// unsigned char xTest ;
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
// xTest = ReadRawRC(BitFramingReg);
// if(xTest == 0x07 )
// { LED_GREEN =0 ;}
// else {LED_GREEN =1 ;while(1){}}
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
// if(status == MI_OK )
// { LED_GREEN =0 ;}
// else {LED_GREEN =1 ;}
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdSelect(unsigned char *pSnr)
{
char status;
unsigned char i;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
// 0x60 = 验证A密钥
// 0x61 = 验证B密钥
// addr[IN]:块地址
// pKey[IN]:密码
// pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
for (i=0; i<6; i++)
{ ucComMF522Buf[i+2] = *(pKey+i); }
for (i=0; i<6; i++)
{ ucComMF522Buf[i+8] = *(pSnr+i); }
// memcpy(&ucComMF522Buf[2], pKey, 6);
// memcpy(&ucComMF522Buf[8], pSnr, 4);
status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// pData[OUT]:读出的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRead(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
// { memcpy(pData, ucComMF522Buf, 16); }
{
for (i=0; i<16; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// pData[IN]:写入的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdWrite(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
//memcpy(ucComMF522Buf, pData, 16);
for (i=0; i<16; i++)
{ ucComMF522Buf[i] = *(pData+i); }
CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:命令卡片进入休眠状态
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
return MI_OK;
}
/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
unsigned char i,n;
ClearBitMask(DivIrqReg,0x04);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i