www.pudn.com > RC522.zip > APP_RC522.c, change:2015-04-14,size:20355b


#include "APP_RC522.h" 
#include "Driver_RC522.h" 
#include "delay.h" 
#include "global.h" 
#include <string.h> 
  
///////////////////////////////////////////////////////////////////// 
//功    能: 程序使用变量和数组初始化 
//参数说明:  无  
//返    回:  无 
///////////////////////////////////////////////////////////////////// 
 
void Variable_Init(void) 
{ 
		decimal=FALSE; 
		pass_mode =FALSE; 
		lock=FALSE; 
		 
		memset(data2,0,sizeof(data2)); 
		data2[0] =10; 
		memset(Card_Type1,0,sizeof(Card_Type1)); 
		memset(Card_ID,0,sizeof(Card_ID)); 
		memset(pasword,0,sizeof(pasword)); 
		memset(savepas,0,sizeof(savepas)); 
		memset(Card_Data,0,sizeof(Card_Data)); 
		memset(Read_Card,0,sizeof(Read_Card)); 
		memset(Default_pass,0xFF,sizeof(Default_pass)); 
	  Default_pass[6]=0xFF; 
	  Default_pass[7]=0x07; 
	  Default_pass[8]=0x80; 
	  Default_pass[9]=0x69; 
 		status=0; 
		key=0;	 
		pre_bit=0; 
		temp_data=0;				 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:寻卡 
//参数说明: 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 
///////////////////////////////////////////////////////////////////// 
u8 PcdRequest(u8 req_code,u8 *pTagType) 
{ 
   u8 status; 
   u16  unLen; 
   u8 ucComMF522Buf[MAXRLEN];  
//  u8 xTest ; 
   ClearBitMask(Status2Reg,0x08); // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1 
   WriteRawRC(BitFramingReg,0x07);// TxLastBits([2-0])表示发送的最后一个字节7位发送 
 
//  xTest = ReadRawRC(BitFramingReg); 
//  if(xTest == 0x07 ) 
 //   { LED_GREEN  =0 ;} 
 // else {LED_GREEN =1 ;while(1){}} 
   SetBitMask(TxControlReg,0x03);// TxControlReg低2位(Tx2RFEn和Tx1RFEn)置1,Tx2和Tx1管脚输出信号调制在13.56MHz的载波上 
  
   ucComMF522Buf[0] = req_code; 
 
   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); // PCD_TRANSCEIVE == 0x0c发送并接收数据 
//     if(status  == MI_OK ) 
//   { LED_GREEN  =0 ;} 
//   else {LED_GREEN =1 ;} 
   if ((status == MI_OK) && (unLen == 0x10))// 发送成功并且接收16位数据 
   {     
       *pTagType     = ucComMF522Buf[0]; 
       *(pTagType+1) = ucComMF522Buf[1];// 接收的卡片类型保存在pTagType中 
   } 
   else 
   {   status = MI_ERR;   } 
    
   return status; 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:防冲撞 
//参数说明: pSnr[OUT]:卡片序列号,4字节 
//返    回: 成功返回MI_OK 
/////////////////////////////////////////////////////////////////////   
u8 PcdAnticoll(u8 *pSnr) 
{ 
    u8 status; 
    u8 i,snr_check=0; 
    u16  unLen; 
    u8 ucComMF522Buf[MAXRLEN];     
 
    ClearBitMask(Status2Reg,0x08); // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1 
    WriteRawRC(BitFramingReg,0x00); // TxLastBits([2-0])表示发送的最后一个字节的所有位都发送 
    ClearBitMask(CollReg,0x80);// 高位置0,所有接收的位在冲突后清除 
  
    ucComMF522Buf[0] = PICC_ANTICOLL1;// 防冲撞(0x93) 
    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);// 置1,回归正常 
    return status; 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:选定卡片 
//参数说明: pSnr[IN]:卡片序列号,4字节 
//返    回: 成功返回MI_OK 
///////////////////////////////////////////////////////////////////// 
u8 PcdSelect(u8 *pSnr) 
{ 
    u8 status; 
    u8 i; 
    u16  unLen; 
    u8 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]);// CRC校验卡片序列号 
   
    ClearBitMask(Status2Reg,0x08);// 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1 
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);// 发送卡片的序列号及其校验码 
     
    if ((status == MI_OK) && (unLen == 0x18))// 接收24位 
    {  
       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 
/////////////////////////////////////////////////////////////////////                
u8 PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr) 
{ 
    u8 status; 
    u16  unLen; 
    u8 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 
/////////////////////////////////////////////////////////////////////  
u8 PcdRead(u8 addr,u8 *pData) 
{ 
    u8 status; 
    u16  unLen; 
    u8 i,ucComMF522Buf[MAXRLEN];  
 
    ucComMF522Buf[0] = PICC_READ; // 0x30,读块 
    ucComMF522Buf[1] = addr; 
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);// 计算CRC,存放在ucComMF522Buf[2]和ucComMF522Buf[3]中 
    
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);// 将4个字节放松出去,并接收数据 
    if ((status == MI_OK) && (unLen == 0x90))// 接收144位(18字节) 
 //   {   memcpy(pData, ucComMF522Buf, 16);   } 
    { 
        for (i=0; i<16; i++) 
        {    *(pData+i) = ucComMF522Buf[i];   }// 将前16字节读出 
    } 
    else 
    {   status = MI_ERR;   } 
     
    return status; 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:写数据到M1卡一块 
//参数说明: addr[IN]:块地址 
//          pData[IN]:写入的数据,16字节 
//返    回: 成功返回MI_OK 
/////////////////////////////////////////////////////////////////////                   
u8 PcdWrite(u8 addr,u8 *pData) 
{ 
    u8 status; 
    u16  unLen; 
    u8 i,ucComMF522Buf[MAXRLEN];  
     
    ucComMF522Buf[0] = PICC_WRITE;// 0xa0 写块 
    ucComMF522Buf[1] = addr; 
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);// 计算CRC 
  
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);// 发送写命令和地址 
 
    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))// 接收低四位为1010 
    {   status = MI_ERR;   } 
         
    if (status == MI_OK) 
    { 
        //memcpy(ucComMF522Buf, pData, 16); 
        for (i=0; i<16; i++) 
        {    ucComMF522Buf[i] = *(pData+i);   }// 16字节数据 
        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);// 两位CRC计算字节 
 
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);// 发送18字节 
        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))// 返回低四位为1010 
        {   status = MI_ERR;   } 
    }    
    return status; 
} 
 
 
 
///////////////////////////////////////////////////////////////////// 
//功    能:命令卡片进入休眠状态 
//返    回: 成功返回MI_OK 
///////////////////////////////////////////////////////////////////// 
u8 PcdHalt(void) 
{ 
   u8 status; 
    u16  unLen; 
    u8 ucComMF522Buf[MAXRLEN];  
 
    ucComMF522Buf[0] = PICC_HALT;// 0x50,休眠 
    ucComMF522Buf[1] = 0; 
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);// 计算校验位 
  
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);// 发送 
 
    return status; 
} 
 
///////////////////////////////////////////////////////////////////// 
//用MF522计算CRC16函数 
///////////////////////////////////////////////////////////////////// 
void CalulateCRC(u8 *pIndata,u8 len,u8 *pOutData) 
{ 		 
	u8 i,n; 
	ClearBitMask(DivIrqReg,0x04); // CRCIRQ清零 
	WriteRawRC(CommandReg,PCD_IDLE); // 空闲命令 
	SetBitMask(FIFOLevelReg,0x80); // FIFOLevelReg中FlushBuffer位置1,表示缓冲区读和写指针清除,即缓冲区无数据,用来存放一下批数据,ErrReg的BufferOvfl清楚  
	for (i=0; i<len; i++) 
	{ WriteRawRC(FIFODataReg, *(pIndata+i)); } // 将数据写入缓冲区 
	WriteRawRC(CommandReg, PCD_CALCCRC); // 启动CRC计算,结果存于CRCResultReg中 
	i = 0xFF; 
	do 
	{ 
		n = ReadRawRC(DivIrqReg); 
		i--; 
	} 
	while ((i!=0) && !(n&0x04)); // CRCIRQ置位,当CRC有效且所有数据被处理则需要置1,退出循环,或者是执行了127次读取认为完成CRC也退出循环 
	pOutData[0] = ReadRawRC(CRCResultRegL); 
	pOutData[1] = ReadRawRC(CRCResultRegM); // 计算结果输出到pOutData中  
 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:复位RC522 
//返    回: 成功返回MI_OK 
///////////////////////////////////////////////////////////////////// 
u8 PcdReset(void) 
{ 
		MF522REST_H; 
	  delay_ms(2); 
		MF522REST_L; 
		delay_ms(2); 
		MF522REST_H; 
	  delay_ms(2); 
    WriteRawRC(CommandReg,PCD_RESETPHASE);// 0x0F,软件复位 
		delay_ms(2); 
    	 
    WriteRawRC(ModeReg,0x3D);           // 和Mifare卡通讯,CRC初始值0x6363 WriteRawRC(TReloadRegL,30); // 48 
    WriteRawRC(TReloadRegL,30);         //16位定时器高位       
    WriteRawRC(TReloadRegH,0);          //16位定时器低位 
    WriteRawRC(TModeReg,0x8D);          // 10001101(141):发送完开始计时,接收时停止计时,自动重装 
    WriteRawRC(TPrescalerReg,0x3E);     // 00111110(62),3390 定时时间:3391*49/6.78=24.5ms 
    WriteRawRC(TxAutoReg,0x40);         // 控制驱动天线  
	 
    return MI_OK; 
} 
////////////////////////////////////////////////////////////////////// 
//设置RC632的工作方式  
////////////////////////////////////////////////////////////////////// 
u8 M500PcdConfigISOType(u8 type)  //寻找A卡 
{ 
    if (type == 'A')                     //ISO14443_A 
   {  
       ClearBitMask(Status2Reg,0x08); //as default    
 
 /*     WriteRawRC(CommandReg,0x20);    //as default    
       WriteRawRC(ComIEnReg,0x80);     //as default 
       WriteRawRC(DivlEnReg,0x0);      //as default 
	   WriteRawRC(ComIrqReg,0x04);     //as default 
	   WriteRawRC(DivIrqReg,0x0);      //as default 
	   WriteRawRC(Status2Reg,0x0);//80    //trun off temperature sensor 
	   WriteRawRC(WaterLevelReg,0x08); //as default 
       WriteRawRC(ControlReg,0x20);    //as default 
	   WriteRawRC(CollReg,0x80);    //as default 
*/ 
       WriteRawRC(ModeReg,0x3D);//3F 
 /*	   WriteRawRC(TxModeReg,0x0);      //as default??? 
	   WriteRawRC(RxModeReg,0x0);      //as default??? 
	   WriteRawRC(TxControlReg,0x80);  //as default??? 
 
	   WriteRawRC(TxSelReg,0x10);      //as default??? 
   */ 
       WriteRawRC(RxSelReg,0x86);//84 // 内部模拟部分的调制信号作为非接触式UART输入,发送后接收器启动延时6个位时钟 
  //      WriteRawRC(RxThresholdReg,0x84);//as default 
 //      WriteRawRC(DemodReg,0x4D);      //as default 
 
 //      WriteRawRC(ModWidthReg,0x13);//26 
       WriteRawRC(RFCfgReg,0x7F);   //4F// 接收信号电压增益23dB 
 	/*   WriteRawRC(GsNReg,0x88);        //as default??? 
	   WriteRawRC(CWGsCfgReg,0x20);    //as default??? 
       WriteRawRC(ModGsCfgReg,0x20);   //as default??? 
*/ 
   	   WriteRawRC(TReloadRegL,30);//设置定时器 
 	     WriteRawRC(TReloadRegH,0);  
       WriteRawRC(TModeReg,0x8D); 
 	     WriteRawRC(TPrescalerReg,0x3E); 
 	    
 
  //     PcdSetTmo(106); 
	    		delay_ms(10); 
       PcdAntennaOn(); 
   } 
   else 
		{return 1;} 
 
    
   return MI_OK; 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:置RC522寄存器位 
//参数说明:reg[IN]:寄存器地址 
//          mask[IN]:置位值 
///////////////////////////////////////////////////////////////////// 
void SetBitMask(u8 reg,u8 mask)   
{ 
    u8 tmp = 0x0; 
    tmp = ReadRawRC(reg); 
    WriteRawRC(reg,tmp | mask);  // set bit mask 
} 
  
///////////////////////////////////////////////////////////////////// 
//功    能:清RC522寄存器位 
//参数说明:reg[IN]:寄存器地址 
//          mask[IN]:清位值 
///////////////////////////////////////////////////////////////////// 
void ClearBitMask(u8 reg,u8 mask)   
{ 
    u8 tmp = 0x0; 
    tmp = ReadRawRC(reg); 
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask 
  }  
 
///////////////////////////////////////////////////////////////////// 
//功    能:通过RC522和ISO14443卡通讯 
//参数说明:Command[IN]:RC522命令字 
//          pInData[IN]:通过RC522发送到卡片的数据 
//          InLenByte[IN]:发送数据的字节长度 
//          pOutData[OUT]:接收到的卡片返回数据 
//          *pOutLenBit[OUT]:返回数据的位长度 
//返    回: 成功返回MI_OK 
///////////////////////////////////////////////////////////////////// 
u8 PcdComMF522(u8 Command,  
                 u8 *pInData,  
                 u8 InLenByte, 
                 u8 *pOutData,  
                 u16  *pOutLenBit) 
{ 
    u8 status = MI_ERR; 
    u8 irqEn   = 0x00; 
    u8 waitFor = 0x00; 
    u8 lastBits; 
    u8 n; 
    u16 i; 
    switch (Command) 
    { 
       case PCD_AUTHENT://验证密匙 
          irqEn   = 0x12; 
          waitFor = 0x10; 
          break; 
       case PCD_TRANSCEIVE://发送并接收数据 
          irqEn   = 0x77; 
          waitFor = 0x30; 
          break; 
       default: 
         break; 
    } 
    
    WriteRawRC(ComIEnReg,irqEn|0x80);//允许除定时器中断外的所有中断 
    ClearBitMask(ComIrqReg,0x80);    //屏蔽位清除 
    WriteRawRC(CommandReg,PCD_IDLE);//取消当前命令 
    SetBitMask(FIFOLevelReg,0x80);//清除FIFO中的读写指针 
     
    for (i=0; i<InLenByte; i++) 
    {  
     WriteRawRC(FIFODataReg, pInData[i]);  //写寻卡命令  
    } 
    WriteRawRC(CommandReg, Command);//发送并且接收数据 
    if (Command == PCD_TRANSCEIVE) 
    {   
     SetBitMask(BitFramingReg,0x80); //相当于发送STARTSENG 
    } 
     
//    i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms 
	 i = 2000; 
    do  
    { 
         n = ReadRawRC(ComIrqReg); 
         i--; 
    } 
    while ((i!=0) && !(n&0x01) && !(n&waitFor)); 
    ClearBitMask(BitFramingReg,0x80);//相当于清除STARTSENG 
	       
    if (i!=0)//定时时间到,定时变量没有递减到0 
    {     
			 if(!(ReadRawRC(ErrorReg)&0x1B)) 
			 { 
					 status = MI_OK; 
					 if (n & irqEn & 0x01) 
					 {  
            status = MI_NOTAGERR;  
           } 
					 if (Command == PCD_TRANSCEIVE) 
					 { 
							n = ReadRawRC(FIFOLevelReg); 
							lastBits = ReadRawRC(ControlReg) & 0x07; 
							if (lastBits) 
							{  
               *pOutLenBit = (n-1)*8 + lastBits;  
              } 
							else 
							{  
               *pOutLenBit = n*8;    
              } 
							if (n == 0) 
							{  
               n = 1;   
              } 
							if (n > MAXRLEN) 
							{  
               n = MAXRLEN;  
              } 
							for (i=0; i<n; i++) 
							{  
               pOutData[i] = ReadRawRC(FIFODataReg);   
              } 
					} 
			 } 
			 else 
			 {   status = MI_ERR;   } 
    } 
    SetBitMask(ControlReg,0x80);           // stop timer now 
   WriteRawRC(CommandReg,PCD_IDLE);  
   return status; 
} 
 
 
///////////////////////////////////////////////////////////////////// 
//开启天线   
//每次启动或关闭天险发射之间应至少有1ms的间隔 
///////////////////////////////////////////////////////////////////// 
void PcdAntennaOn() 
{ 
    u8 i; 
    i = ReadRawRC(TxControlReg); 
    if (!(i & 0x03)) 
    { 
        SetBitMask(TxControlReg, 0x03);//设置该位时,TX1,TX2引脚的输出信号将传递发送数据调制的13.56MHz的能量载波信号 
    } 
} 
 
 
///////////////////////////////////////////////////////////////////// 
//关闭天线 
///////////////////////////////////////////////////////////////////// 
void PcdAntennaOff() 
{ 
    ClearBitMask(TxControlReg, 0x03);//屏蔽该位时,TX1,TX2引脚的输出信号将不能传递发送数据调制的13.56MHz的能量载波信号 
} 
 
 
///////////////////////////////////////////////////////////////////// 
//功    能:扣款和充值 
//参数说明: dd_mode[IN]:命令字 
//               0xC0 = 扣款 
//               0xC1 = 充值 
//          addr[IN]:钱包地址 
//          pValue[IN]:4字节增(减)值,低位在前 
//返    回: 成功返回MI_OK 
/////////////////////////////////////////////////////////////////////                  
u8 PcdValue(u8 dd_mode,u8 addr,u8 *pValue) 
{ 
    u8 status; 
    u16  unLen; 
    u8 ucComMF522Buf[MAXRLEN];  
     
    ucComMF522Buf[0] = dd_mode;// 充值还是扣款(加还是减) 
    ucComMF522Buf[1] = addr;//钱包地址(写卡位置) 
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);//计算CRC 
  
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);//传输命令和地址 
 
    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))//卡片返回1010 
    {   status = MI_ERR;   } 
         
    if (status == MI_OK) 
    { 
        memcpy(ucComMF522Buf, pValue, 4); 
 //       for (i=0; i<16; i++) 
 //       {    ucComMF522Buf[i] = *(pValue+i);   } 
        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 
        unLen = 0; 
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);//传输充值或者扣款数据信息 
        if (status != MI_ERR) 
        {    status = MI_OK;    } 
    } 
     
    if (status == MI_OK) 
    { 
        ucComMF522Buf[0] = PICC_TRANSFER;//保存缓冲区中的数据 
        ucComMF522Buf[1] = addr;//保存缓冲区中的地址 
        CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); //计算CRC 
    
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);//发送缓冲区中的命令信息 
 
        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))//卡号返回1010B 
        {   status = MI_ERR;   } 
    } 
    return status; 
} 
 
///////////////////////////////////////////////////////////////////// 
//功    能:备份钱包 
//参数说明: sourceaddr[IN]:源地址 
//          goaladdr[IN]:目标地址 
//返    回: 成功返回MI_OK 
///////////////////////////////////////////////////////////////////// 
u8 PcdBakValue(u8 sourceaddr, u8 goaladdr) 
{ 
    u8 status; 
    u16  unLen; 
    u8 ucComMF522Buf[MAXRLEN];  
 
    ucComMF522Buf[0] = PICC_RESTORE;//调用数据块到数据缓冲区 
    ucComMF522Buf[1] = sourceaddr;//源地址 
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);//计算CRC 
  
    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) 
    { 
        ucComMF522Buf[0] = 0; 
        ucComMF522Buf[1] = 0; 
        ucComMF522Buf[2] = 0; 
        ucComMF522Buf[3] = 0; 
        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 
  
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen); 
        if (status != MI_ERR) 
        {    status = MI_OK;    } 
    } 
     
    if (status != MI_OK) 
    {    return MI_ERR;   } 
     
    ucComMF522Buf[0] = PICC_TRANSFER;//保存缓冲区数据信息 
    ucComMF522Buf[1] = goaladdr;//目的地址 
 
    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;   } 
 
    return status; 
}