MFRC522读写测试

追加问题(3)

1.MFRC522卡片读写(个人理解)
RC522原理及M1操作原理,不在此赘述,网上例程很多,只在此附上本人调试时遇见的问题及测试代码,供大家参考,使用的是STM32F103C8T6,如有问题,轻喷!!
问题(1):MFRC522通信没反应
最开始使用的是硬件SPI进行通信,发现没有反应,通过示波器观看,并不是通信数据乱码,排除波特率问题,SPI通信的读写底层是在EEPROM中实验过的没有问题,示波器的波形显示的也是瞬间的高低电平,不知道是什么原因,参考网上的例程,使用软件模拟的SPI通信,数据通信正常。
问题(2):在卡片验证密匙及读写操作时,涉及到一个读写地址的问题,如下:

//********************************************************************
//功    能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥 
//          addr[IN]:块地址
//          pKey[IN]:密码
//          pSnr[IN]:卡片序列号,4字节
//返    回: 验证结果
//********************************************************************              
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);  
		}
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    {  
  		status = MI_ERR;   
		}
    return status;
}

addr[IN]:块地址,这个是在这个函数中封装好的,共有16个扇区,每个扇区4个块,如第一个扇区对应的就是块0,1,2,3,第二个扇区对应4,5,6,7,依次类推。addr取值就是0~63.
问题(3)块密码怎么确认;想了一下,单纯的从读写来判断块写入,证明写入没有问题的还是缺乏点说服力,又换了一个方法证明写入没有错误,及证明问题(2)说的块地址问题没有错误
首先要在手机下载一个NFC WRITER的APP,也可能是其他的APP,不同的应用商城搜出来的应该不一样,我用的图标如下:
在这里插入图片描述
我在后续的实验里面写的都是块4,用这个软件可以看到写入的数据,并且还能看到每一个块的密码,同时也可以证明我在问题(2)中说的块地址的判别方法没有问题
在这里插入图片描述

2.参考代码
main.c


#include "stm32f10x.h"                  // Device header
#include "SPI1.h"
#include "Delay.h"
#include "USART2.h"
#include "RC522.h"
int main ()
{
  USART2_INIT (  ) ;
	USART2_GPIO (  ) ;
	
	SPI1_GPIO_Init ( ) ;
	
	PcdReset ( ) ;
	M500PcdConfigISOType ( 'A' ) ;
	
	while ( 1 )
	{
		if ( ( FLAG.CARD_TYPE_FLAG = PcdRequest ( PICC_REQALL, CARD_TYPE ) ) != MI_OK )   
		{
				FLAG.CARD_TYPE_FLAG = PcdRequest ( PICC_REQALL, CARD_TYPE );		
		}
		if ( FLAG.CARD_TYPE_FLAG == MI_OK  )
		{
			  FLAG.CARD_UID_FLAG =  PcdAnticoll ( CARD_UID ) ;
			if (  FLAG.CARD_UID_FLAG == MI_OK ) 
			{
				printf ("\r\n 卡片类型: %02x %02x  \r\n", CARD_TYPE[ 0 ], CARD_TYPE[ 1 ]);
				printf ("\r\n 卡片UID: %x %x %x %x \r\n", CARD_UID[ 0 ], CARD_UID[ 1 ], CARD_UID[ 2 ], CARD_UID [ 3 ] );
				FLAG.CARD_SELECT_FLAG = PcdSelect(CARD_UID ) ;			
				if (FLAG.CARD_SELECT_FLAG == MI_OK)
				{
					printf ("\r\n 选卡成功  \r\n");
				}
				else 
				{
					printf ("\r\n 选卡失败  \r\n");
				}
				FLAG.KEY_A_FLAG = PcdAuthState(  KEY_A ,4,KEY2,CARD_UID) ;
				if (FLAG.KEY_A_FLAG == MI_OK)
				{
					printf ("\r\n 密码A验证成功  \r\n");
				}
				else 
				{
					printf ("\r\n 密码A验证失败  \r\n");
				}
				FLAG.KEY_B_FLAG = PcdAuthState(  KEY_B ,4,KEY2,CARD_UID) ;
				if (FLAG.KEY_B_FLAG == MI_OK)
				{
					printf ("\r\n 密码B验证成功  \r\n");
				}
				else 
				{
					printf ("\r\n 密码B验证失败  \r\n");
				}
//				PcdWrite( 4,name) ;  //写入块4
//				
//				PcdRead(4,RX_FROM_RC522) ;
//				printf ("\r\n %s  \r\n",name);
				
				//已测试,读写成功
				PcdWrite( 4,TX_TO_RC522) ;  //写入块4
				
				PcdRead(4,RX_FROM_RC522) ;

			  printf ("\r\n 块4读取的数据: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x  \r\n", 
				RX_FROM_RC522[0],RX_FROM_RC522[1],RX_FROM_RC522[2],RX_FROM_RC522[3],
				RX_FROM_RC522[4],RX_FROM_RC522[5],RX_FROM_RC522[6],RX_FROM_RC522[7],
				RX_FROM_RC522[8],RX_FROM_RC522[9],RX_FROM_RC522[10],RX_FROM_RC522[11],
				RX_FROM_RC522[12],RX_FROM_RC522[13],RX_FROM_RC522[14],RX_FROM_RC522[15] );		
			}	
		}	
		Delay_ms (1000) ;
	}
}

RC522.C


/*
1.MFRC522地址格式:共8位。最高位bit7是读写位,0写1读;bit6-bit1共6位地址信息,bit0常值为0
2.在宏定义的读写函数里面已经包含了等待延时
*/

#include "stm32f10x.h"                  // Device header
#include "RC522.h" 
#include <string.h> 
#include "SPI1.h"
#include "Delay.h"
#define MAXRLEN 18  

struct FLAG FLAG;

unsigned char name[] = "齐泽" ;
uint8_t KEY1[6] = { 0X00,0X00,0X00,0X00,0X00,0X00} ;
uint8_t KEY2[6] = { 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF} ;
uint8_t CARD_TYPE[2] = { 0 } ;
uint8_t CARD_UID[4]  = { 0 } ;
uint8_t TX_TO_RC522[16]   = {0xAA, 0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0A,0X0B,0X0C,0X0D,0X0E,0XAA} ;  //实验数据 
uint8_t RX_FROM_RC522[16] = { 0 } ;
/*********************************SPI读写配置***********************************************/
//********************************************************************
//功    能:写RC632寄存器
//参数说明:Address[IN]:6位寄存器地址
//          value[IN]:写入的值
//返   回: 无
//********************************************************************
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char  ucAddr;
	
    ucAddr = ((Address<<1)&0x7E);
	
	  MFRC522_SPI_CS_ON ;
	  Delay_us (500) ;
	  MFRC522_SPI_WRITE(ucAddr) ;
	  MFRC522_SPI_WRITE(value) ;
	  MFRC522_SPI_CS_OFF ;
}

//********************************************************************
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
//********************************************************************
unsigned char ReadRawRC(unsigned char Address)
{
     unsigned char  ucAddr ;
     unsigned char ucResult=0;

     ucAddr = ((Address<<1)&0x7E)|0x80;
	   MFRC522_SPI_CS_ON ;
	   Delay_us (500) ;
	   MFRC522_SPI_WRITE(ucAddr) ;
	   ucResult =MFRC522_SPI_READ ( ) ;
	   Delay_us (500) ;
	   MFRC522_SPI_CS_OFF ;
	
     return ucResult;
}

/******************************************************************************************/


/*****************************MFRC522配置函数**********************************/


//********************************************************************
//功    能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:置位值
//返   回:无
//********************************************************************
void SetBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg,tmp | mask);  // set bit mask
}

//********************************************************************
//功    能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:清位值
//返   回:无
//********************************************************************
void ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}
//********************************************************************
//功    能:开启天线
//参数说明:无
//返    回:无
//********************************************************************

void PcdAntennaOn ( void )
{
    uint8_t uc;
    uc = ReadRawRC ( TxControlReg );
    if ( ! ( uc & 0x03 ) )
			SetBitMask(TxControlReg, 0x03); //开启TX1/TX2载波调制
}

//********************************************************************
//功    能:关闭天线
//参数说明:无
//返    回:无
//********************************************************************
void PcdAntennaOff()
{
    ClearBitMask(TxControlReg, 0x03);//关闭TX1/TX2载波调制
}

//********************************************************************
//设置RC632的工作方式 
//功    能:设置RC632的工作方式
//参数说明:type 卡片类型
//返    回:设置结果
//********************************************************************
char M500PcdConfigISOType(unsigned char type)
{

	if ( type == 'A')                     //ISO14443_A
  {
		ClearBitMask ( Status2Reg, 0x08 );      //该位置1表示正在进行密码验证或者读写操作
		
    WriteRawRC ( ModeReg, 0x3D );//3F      //开启射频场,设置信号引脚高电平有效,crc初始值6363
		
		WriteRawRC ( RxSelReg, 0x86 );//84     //设置调制信号来字内部模拟部分;设置RX等待时钟
		
		WriteRawRC( RFCfgReg, 0x7F );   //4F   //配置接收增益
		
		WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
		
		WriteRawRC ( TReloadRegH, 0 );        //配置定时器重装载数值
		
		WriteRawRC ( TModeReg, 0x8D );        //TModeReg高4位,设置定时器在数据传输完毕时自动开启,非定时器同步模式,定时器计数到0
		
		WriteRawRC ( TPrescalerReg, 0x3E );   //TModeReg低4位和TPrescalerReg共同构成12位定时器分频器,定时器时钟为6.78M/0X0D3E=2Khz
		
		Delay_us (10) ;
		
		PcdAntennaOn ();                      //开天线
		
		return  MI_OK;
	}
 else
	{
		 return MI_ERR;
	 }
}

//********************************************************************
//功    能:复位RC522
//参数说明:无
//返    回:设置结果
//********************************************************************
char PcdReset(void)
{
    MFRC522_SPI_RST_OFF ;                        //拉高复位
    Delay_us (10) ;
    MFRC522_SPI_RST_ON ;                         //拉低复位
    Delay_us (10) ;
    MFRC522_SPI_RST_OFF ;                        //拉低复位
    Delay_us (10) ;
    WriteRawRC(CommandReg,PCD_RESETPHASE);       //写指令,复位RC522
	  while ( ReadRawRC ( CommandReg ) & 0x10 )    //等待RC522复位成功后,开始唤醒
			;                                      
	
    Delay_us (10) ;
   
		WriteRawRC ( ModeReg, 0x3D );            //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363	
		WriteRawRC ( TReloadRegL, 30 );          //16位定时器低位    
		WriteRawRC ( TReloadRegH, 0 );			     //16位定时器高位	
		WriteRawRC ( TModeReg, 0x8D );				   //定义内部定时器的设置	
		WriteRawRC ( TPrescalerReg, 0x3E );			 //设置定时器分频系数	
		WriteRawRC ( TxAutoReg, 0x40 );				   //调制发送信号为100%ASK    
    return MI_OK;
}

/****************************************************************************************************/

/*****************************卡片操作函数************************************************************/

//********************************************************************
//功    能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
//          pInData[IN]:通过RC522发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOutData[OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
//返    回:通讯结果
//********************************************************************
char PcdComMF522(unsigned char Command, unsigned char *pInData, unsigned char InLenByte,unsigned char *pOutData,  unsigned int  *pOutLenBit)

{
    char cStatus = MI_ERR;
    u8 ucIrqEn   = 0x00;
    u8 ucWaitFor = 0x00;
    u8 ucLastBits;
    u8 ucN;
    u32 ul;
    switch ( Command )
    {
       case PCD_AUTHENT:		  //Mifare认证
          ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEn
          ucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位
          break;
			 
       case PCD_TRANSCEIVE:		//接收发送 发送接收
          ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
          ucWaitFor = 0x30;		//寻卡等待时候 查询接收中断标志位与 空闲中断标志位
          break;
			 
       default:
         break;
			 
    }
   
    WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );	           //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
    ClearBitMask ( ComIrqReg, 0x80 );			               //Set1该位清零时,CommIRqReg的屏蔽位清零
    WriteRawRC ( CommandReg, PCD_IDLE );	    	         //写空闲命令
    SetBitMask ( FIFOLevelReg, 0x80 );			             //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
    
    for ( ul = 0; ul < InLenByte; ul ++ )
		  WriteRawRC ( FIFODataReg, pInData [ ul ] );    		//写数据进FIFOdata
			
    WriteRawRC ( CommandReg, Command );					        //写命令
   
    
    if ( Command == PCD_TRANSCEIVE )
			SetBitMask(BitFramingReg,0x80);  				          //StartSend置位启动数据发送 该位与收发命令使用时才有效
    
    ul = 1000;//根据时钟频率调整,操作M1卡最大等待时间25ms
		
    do 														//认证 与寻卡等待时间	
    {
         ucN = ReadRawRC ( ComIrqReg );							//查询事件中断
         ul --;
    } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );		//退出条件i=0,定时器中断,与写空闲命令
		
    ClearBitMask ( BitFramingReg, 0x80 );					//清理允许StartSend位
		
    if ( ul != 0 )
    {
			if ( ! ( ReadRawRC ( ErrorReg ) & 0x1B ) )			//读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
			{
				cStatus = MI_OK;
				
				if ( ucN & ucIrqEn & 0x01 )					//是否发生定时器中断
				  cStatus = MI_NOTAGERR;   
					
				if ( Command == PCD_TRANSCEIVE )
				{
					ucN = ReadRawRC ( FIFOLevelReg );			//读FIFO中保存的字节数
					
					ucLastBits = ReadRawRC ( ControlReg ) & 0x07;	//最后接收到得字节的有效位数
					
					if ( ucLastBits )
						* pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;   	//N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
					else
						* pOutLenBit = ucN * 8;   					//最后接收到的字节整个字节有效
					
					if ( ucN == 0 )		
            ucN = 1;    
					
					if ( ucN > MAXRLEN )
						ucN = MAXRLEN;   
					
					for ( ul = 0; ul < ucN; ul ++ )
					  pOutData [ ul ] = ReadRawRC ( FIFODataReg );   
					
					}
					
      }
			
			else
				cStatus = MI_ERR;   
			
    }
   
   SetBitMask ( ControlReg, 0x80 );           // stop timer now
   WriteRawRC ( CommandReg, PCD_IDLE ); 
		 
		
   return cStatus;
		
		
}



//********************************************************************
//功    能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥 
//          addr[IN]:块地址
//          pKey[IN]:密码
//          pSnr[IN]:卡片序列号,4字节
//返    回: 验证结果
//********************************************************************              
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);  
		}
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    {  
  		status = MI_ERR;   
		}
    return status;
}

//********************************************************************
//功    能:用MF522计算CRC16函数
//参数说明: *pIndata:待计算数据
//          len    :  数据长度
//          *pOutData:CRC校验码
//返    回: 计算结果
//********************************************************************
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<len; i++)
    {   
		  WriteRawRC(FIFODataReg, *(pIndata+i));   
		}
    WriteRawRC(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do 
    {
        n = ReadRawRC(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));
    pOutData[0] = ReadRawRC(CRCResultRegL);
    pOutData[1] = ReadRawRC(CRCResultRegM);
}
//********************************************************************
//功    能:寻卡
//参数说明: req_code :寻卡类型代码
//           *pTagType:存放卡片类型
//返    回: 寻卡结果
//******************************************************************** 

char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
   char cStatus;  
	 u8 ucComMF522Buf [ MAXRLEN ]; 
   u32 ulLen;
	
 
   ClearBitMask ( Status2Reg, 0x08 );	//清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
   WriteRawRC ( BitFramingReg, 0x07 );	//	发送的最后一个字节的 七位
   SetBitMask ( TxControlReg, 0x03 );	//TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
 
   ucComMF522Buf [ 0 ] = req_code;		//存入 卡片命令字
 
   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,	ucComMF522Buf, 1, ucComMF522Buf, & ulLen );	//寻卡  
  
   if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) )	//寻卡成功返回卡类型 
   {    
       * pTagType = ucComMF522Buf [ 0 ];
       * ( pTagType + 1 ) = ucComMF522Buf [ 1 ];
   }
	 
   else
     cStatus = MI_ERR;
 
   
   return cStatus;
	 
	 
}


//********************************************************************
//功    能:防冲撞读卡
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 防冲撞读卡结果
//********************************************************************  
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字节
//返    回: 选卡结果
//********************************************************************
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;
}
//********************************************************************
//功    能:命令卡片进入休眠状态
//返    回: 卡片休眠结果
//********************************************************************
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 status;
}
//********************************************************************
//功    能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
//          pData[OUT]:读出的数据,16字节
//返    回: 读卡结果
//********************************************************************
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字节
//返    回: 写卡结果
//********************************************************************                 
char PcdWrite(unsigned char addr,unsigned char *pData)
{
    uint8_t 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;
}

/*****************************************************************************/

RC522.h

#ifndef __RC522_H
#define __RC522_H
#include "stm32f10x.h"                  // Device header
#include "SPI1.h"

extern uint8_t CARD_TYPE[2] ;
extern uint8_t CARD_UID[4] ;
extern uint8_t TX_TO_RC522[16] ;
extern uint8_t RX_FROM_RC522[16] ;
extern struct FLAG FLAG;
extern uint8_t KEY1[6] ;
extern uint8_t KEY2[6] ;
extern unsigned char name[] ;


struct FLAG
{
	uint16_t CARD_TYPE_FLAG ;
	uint16_t CARD_UID_FLAG ;
	uint16_t CARD_SELECT_FLAG ;
	uint16_t KEY_A_FLAG ;
	uint16_t KEY_B_FLAG ;
	uint16_t CARD_WRITE_FLAG ;
	uint16_t CARD_READ_FLAG ;
} ;

//****************KEY**************
#define  KEY_A   0x60
#define  KEY_B   0x61

//***************************************

//****************CARD TYPE**************
#define  Mifare_UltraLight   0x4400
#define  Mifare_One_S50      0x0400
#define  Mifare_One_S70      0x0200
#define  Mifare_Pro(X)       0x0800
#define  Mifare_DESFire      0x4403
//***************************************

//*************寻卡方式******************
#define  SEARCH_CARD_ALL        0x52
#define  SEARCH_CARD_NOSLEEP    0x26




//MF522命令字
/
#define PCD_IDLE              0x00               //取消当前命令
#define PCD_AUTHENT           0x0E               //验证密钥
#define PCD_RECEIVE           0x08               //接收数据
#define PCD_TRANSMIT          0x04               //发送数据
#define PCD_TRANSCEIVE        0x0C               //发送并接收数据
#define PCD_RESETPHASE        0x0F               //复位
#define PCD_CALCCRC           0x03               //CRC计算

/
//Mifare_One卡片命令字
/
#define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
#define PICC_REQALL           0x52               //寻天线区内全部卡
#define PICC_ANTICOLL1        0x93               //防冲撞
#define PICC_ANTICOLL2        0x95               //防冲撞
#define PICC_AUTHENT1A        0x60               //验证A密钥
#define PICC_AUTHENT1B        0x61               //验证B密钥
#define PICC_READ             0x30               //读块
#define PICC_WRITE            0xA0               //写块
#define PICC_DECREMENT        0xC0               //扣款
#define PICC_INCREMENT        0xC1               //充值
#define PICC_RESTORE          0xC2               //调块数据到缓冲区
#define PICC_TRANSFER         0xB0               //保存缓冲区中数据
#define PICC_HALT             0x50               //休眠

/
//MF522 FIFO长度定义
/
#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte

/
//MF522寄存器定义
/
// PAGE 0
#define     RFU00                 0x00    
#define     CommandReg            0x01    
#define     ComIEnReg             0x02    
#define     DivlEnReg             0x03    
#define     ComIrqReg             0x04    
#define     DivIrqReg             0x05
#define     ErrorReg              0x06    
#define     Status1Reg            0x07    
#define     Status2Reg            0x08    
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1     
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2    
#define     RFU20                 0x20  
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
// PAGE 3      
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39  
#define     TestDAC2Reg           0x3A   
#define     TestADCReg            0x3B   
#define     RFU3C                 0x3C   
#define     RFU3D                 0x3D   
#define     RFU3E                 0x3E   
#define     RFU3F		              0x3F

/
//和MF522通讯时返回的错误代码
/
#define MI_OK                          0
#define MI_NOTAGERR                    (1)
#define MI_ERR                         (2)


/
//函数原型
/
void PcdAntennaOn ( void ) ;        //开启天线
char PcdReset(void);
void PcdAntennaOn(void);
void PcdAntennaOff(void);
char PcdRequest(unsigned char req_code,unsigned char *pTagType);   
char PcdAnticoll(unsigned char *pSnr);
char PcdSelect(unsigned char *pSnr);         
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);     
char PcdRead(unsigned char addr,unsigned char *pData);     
char PcdWrite(unsigned char addr,unsigned char *pData);    
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);   
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);                                 
char PcdHalt(void);
char PcdComMF522(unsigned char Command, 
                 unsigned char *pInData, 
                 unsigned char InLenByte,
                 unsigned char *pOutData, 
                 unsigned int  *pOutLenBit);
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);
void WriteRawRC(unsigned char Address,unsigned char value);
unsigned char ReadRawRC(unsigned char Address); 
void SetBitMask(unsigned char reg,unsigned char mask); 
void ClearBitMask(unsigned char reg,unsigned char mask); 
char M500PcdConfigISOType(unsigned char type);
void delay_10ms(unsigned int _10ms);
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);
/
#endif 

3.代码运行结果
在这里插入图片描述

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值