追加问题(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.代码运行结果