📄 mfrc522.c
字号:
/**************************************Copyright (c)*************************************
** 广州周立功单片机发展有限公司
** 研 究 所
** 产品一部
**
** http://www.zlgmcu.com
**
**--------------文件信息----------------------------------------------------------------
** 文 件 名: MFRC522.C
** 文件描述: MF RC522底层程序
** 版 本: V1.0
** 创 建 人: 朱旻
** 创建日期: xxxx.xx.xx
** 最后修改日期:
**=======================================================================================
**-----------------修改记录--------------------------------------------------------------
** 修改内容: 1、 修改文件结构
** 当前版本:
** 修 改 人: 曾本森
** 修改日期: 2007.09.22
** 注 意:
****************************************************************************************/
#define MIFARE_GLOBALS
#include "LPC900SPI.h"
#include "RC522Reg.h"
#include "OpCtrl.h"
#include "Mifare.h"
#include "main.h"
//=======================================================================================
typedef struct
{
unsigned char cmd; //!< command code
char status; //!< communication status
unsigned char nBytesSent; //!< how many bytes already sent
unsigned char nBytesToSend; //!< how many bytes to send
unsigned char nBytesReceived; //!< how many bytes received
unsigned short nBitsReceived; //!< how many bits received
unsigned char collPos; //collision position
} MfCmdInfo;
volatile MfCmdInfo idata MInfo;
char M522PcdCmd(unsigned char cmd,unsigned char idata *ExchangeBuf);
static void ResetInfo(void)
{
unsigned char i;
unsigned char idata *BfrPtr = (unsigned char idata *)(&MInfo);
for(i=0 ; i<sizeof(MfCmdInfo); i++)
BfrPtr[i] = 0;
}
/****************************************************************************************
** 函数原型: void PcdClose(void);
** 函数功能: 读卡芯片硬件掉电/复位
** 入口参数: -
** 出口参数: -
** 返 回 值: -
** 描 述: 复位脚 NRESTPD = 0
****************************************************************************************/
void PcdClose(void)
{
NRSTPD = 0;
}
/****************************************************************************************
** 函数原型: void SetTimeOut(unsigned int _100us)
** 函数功能: 设置芯片超时时间
** 入口参数: unsigned int _100us ; 设置的超时值×100us
** 出口参数: -
** 返 回 值: -
** 描 述:
****************************************************************************************/
void SetTimeOut(unsigned int _100us)
{
RcSetReg(JREG_TRELOADLO, ((unsigned char)(_100us&0xff)));
RcSetReg(JREG_TRELOADHI, ((unsigned char)((_100us>>8)&0xff)));
}
/****************************************************************************************
** 函数原型: char PcdConfig()
** 函数功能: 读写卡芯片配置
** 入口参数: -
** 出口参数: -
** 返 回 值: 操作结果
** 描 述:
****************************************************************************************/
//char PN511InitAsPcd()
char PcdConfig()
{
unsigned char RegVal;
unsigned char i;
ClosePCD();
SPI_Init();
OpenPCD(); // 低电平脉冲宽度大于100ns即可
for(i=3;i>0;i--)
for(RegVal=200;RegVal>0;RegVal--); // 根据晶振起振情况调整此延时时间
RcSetReg(JREG_CONTROL, 0x10); /*Initator*/
RcSetReg(JREG_MODE, 0x3f); /*ModeDetOff*/
RcSetReg(JREG_GSNOFF, 0x00);
RcSetReg(JREG_TXBITPHASE, 0x80);
RcSetReg(JREG_AUTOTEST, 0x40);
RcSetReg(JREG_TXAUTO, 0x40); /*force to 100% ASK*/
RegVal = RcGetReg(JREG_TXAUTO);
if(RegVal != 0x40)
return STATUS_INIT_ERROR;
/* Set the timer to auto mode, 5ms using operation control commands before HF is switched on to
* guarantee Iso14443-3 compliance of Polling procedure
*/
SetTimeOut(10);
/* Activate the field */
RcModifyReg(JREG_TXCONTROL, 1, JBIT_TX2RFEN | JBIT_TX1RFEN);
/* start timer manually to check the initial waiting time */
RcModifyReg(JREG_CONTROL, 1, JBIT_TSTARTNOW);
/*
* After switching on the timer wait until the timer interrupt occures, so that
* the field is on and the 5ms delay have been passed.
*/
do {
RegVal = RcGetReg(JREG_COMMIRQ);
}
while(!(RegVal & JBIT_TIMERI));
/* Clear the status flag afterwards */
RcSetReg(JREG_COMMIRQ, JBIT_TIMERI);
/*
NOTE: The supported hardware range is bigger, since the prescaler here
is always set to 100 us.
*/
RcSetReg(JREG_TPRESCALER, 0xa6-1);
RcSetReg(JREG_TMODE, 0x82);//82
/* Activate receiver for communication
The RcvOff bit and the PowerDown bit are cleared, the command is not changed. */
RcSetReg(JREG_COMMAND, JCMD_IDLE);
TxConMask = 0x03;
return STATUS_SUCCESS;
}
/*************************************************
Function: M522PcdCmd
Description:
implement a command
Parameter:
cmd command code
ExchangeBuf saved the data will be send to card and the data responed from the card
info some information for the command
Return:
char status of implement
**************************************************/
char M522PcdCmd(unsigned char cmd,
unsigned char idata *ExchangeBuf)
{
char status = STATUS_SUCCESS;
unsigned char idata commIrqEn = 0;
unsigned char idata divIrqEn = 0;
unsigned char idata waitForComm = JBIT_ERRI | JBIT_TXI;
unsigned char idata waitForDiv = 0;
unsigned char idata doReceive = 0;
// unsigned char idata i;
unsigned char idata getRegVal,setRegVal;
unsigned char nbytes, nbits;
/*remove all Interrupt request flags that are used during function,
keep all other like they are*/
RcSetReg(JREG_COMMIRQ, 0x7f); //waitForComm);
RcSetReg(JREG_DIVIRQ, 0x7f); //waitForDiv);
RcSetReg(JREG_FIFOLEVEL, JBIT_FLUSHBUFFER);
/*disable command or set to transceive*/
getRegVal = RcGetReg(JREG_COMMAND);
if(cmd == JCMD_TRANSCEIVE)
{
/*re-init the transceive command*/
setRegVal = (getRegVal & ~JMASK_COMMAND) | JCMD_TRANSCEIVE;
RcSetReg(JREG_COMMAND, setRegVal);//0c
}
else
{
/*clear current command*/
setRegVal = (getRegVal & ~JMASK_COMMAND);
RcSetReg(JREG_COMMAND, setRegVal);
}
switch(cmd)
{
case JCMD_IDLE: /* values are 00, so return immediately after all bytes written to FIFO */
waitForComm = 0;
waitForDiv = 0;
break;
case JCMD_CALCCRC: /* values are 00, so return immediately after all bytes written to FIFO */
waitForComm = 0;
waitForDiv = 0;
break;
case JCMD_TRANSMIT:
commIrqEn = JBIT_TXI | JBIT_TIMERI;
waitForComm = JBIT_TXI;
break;
case JCMD_RECEIVE:
commIrqEn = JBIT_RXI | JBIT_TIMERI; //| JBIT_ERRI;
waitForComm = JBIT_RXI | JBIT_TIMERI; //| JBIT_ERRI;
doReceive = 1;
break;
case JCMD_TRANSCEIVE:
commIrqEn = JBIT_RXI | JBIT_TIMERI; //| JBIT_ERRI;
waitForComm = JBIT_RXI | JBIT_TIMERI; //| JBIT_ERRI;
doReceive = 1;
break;
case JCMD_AUTHENT:
commIrqEn = JBIT_IDLEI | JBIT_TIMERI; //| JBIT_ERRI;
waitForComm = JBIT_IDLEI | JBIT_TIMERI; //| JBIT_ERRI;
break;
case JCMD_SOFTRESET: /* values are 0x00 for IrqEn and for waitFor, nothing to do */
waitForComm = 0;
waitForDiv = 0;
break;
default:
status = STATUS_UNSUPPORTED_COMMAND;
}
if(status == STATUS_SUCCESS)
{
/* activate necessary communication Irq's */
getRegVal = RcGetReg(JREG_COMMIEN);
RcSetReg(JREG_COMMIEN, getRegVal | commIrqEn);
/* activate necessary other Irq's */
getRegVal = RcGetReg(JREG_DIVIEN);
RcSetReg(JREG_DIVIEN, getRegVal | divIrqEn);
/*write data to FIFO
for(i=0; i<MpIsrInfo->nBytesToSend; i++)
{
RcSetReg(JREG_FIFODATA, ExchangeBuf[i]);
}*/
WriteFIFO(ExchangeBuf,MInfo.nBytesToSend);
/*do seperate action if command to be executed is transceive*/
if(cmd == JCMD_TRANSCEIVE)
{
/*TRx is always an endless loop, Initiator and Target must set STARTSEND.*/
RcModifyReg(JREG_BITFRAMING, 1, JBIT_STARTSEND);
}
else
{
getRegVal = RcGetReg(JREG_COMMAND);
RcSetReg(JREG_COMMAND, (getRegVal & ~JMASK_COMMAND) | cmd);
}
/*polling mode*/
getRegVal = 0;
setRegVal = 0;
MIFARE_tmoutcnt = RC522_DELAY555MS;
while(!(waitForComm ? (waitForComm & setRegVal) : 1) ||
!(waitForDiv ? (waitForDiv & getRegVal) :1))
{
setRegVal = RcGetReg(JREG_COMMIRQ);
getRegVal = RcGetReg(JREG_DIVIRQ);
if(MIFARE_tmoutcnt == 0)
break;
}
if(MIFARE_tmoutcnt == 0)
{
status = STATUS_ACCESS_TIMEOUT;
}
else
{
/*store IRQ bits for clearance afterwards*/
waitForComm = (unsigned char)(waitForComm & setRegVal);
waitForDiv = (unsigned char)(waitForDiv & getRegVal);
/*set status to Timer Interrupt occurence*/
if (setRegVal & JBIT_TIMERI)
{
status = STATUS_IO_TIMEOUT;
}
}
}
/*disable all interrupt sources*/
RcModifyReg(JREG_COMMIEN, 0, commIrqEn);
RcModifyReg(JREG_DIVIEN, 0, divIrqEn);
if(doReceive && (status == STATUS_SUCCESS))
{
/*read number of bytes received (used for error check and correct transaction*/
MInfo.nBytesReceived = RcGetReg(JREG_FIFOLEVEL);
nbytes = MInfo.nBytesReceived;
getRegVal = RcGetReg(JREG_CONTROL);
MInfo.nBitsReceived = (unsigned char)(getRegVal & 0x07);
nbits = MInfo.nBitsReceived;
getRegVal = RcGetReg(JREG_ERROR);
/*set status information if error occured*/
if(getRegVal)
{
if(getRegVal & JBIT_COLLERR)
status = STATUS_COLLISION_ERROR; /* Collision Error */
else if(getRegVal & JBIT_PARITYERR)
status = STATUS_PARITY_ERROR; /* Parity Error */
if(getRegVal & JBIT_PROTERR)
status = STATUS_PROTOCOL_ERROR; /* Protocoll Error */
else if(getRegVal & JBIT_BUFFEROVFL)
status = STATUS_BUFFER_OVERFLOW; /* BufferOverflow Error */
else if(getRegVal & JBIT_CRCERR)
{ /* CRC Error */
if(MInfo.nBytesReceived == 0x01 &&
(MInfo.nBitsReceived == 0x04 ||
MInfo.nBitsReceived == 0x00))
{ /* CRC Error and only one byte received might be a Mifare (N)ACK */
ExchangeBuf[0] = RcGetReg(JREG_FIFODATA);
MInfo.nBytesReceived = 1;
status = STATUS_ACK_SUPPOSED; /* (N)ACK supposed */
}
else
status = STATUS_CRC_ERROR; /* CRC Error */
}
else if(getRegVal & JBIT_TEMPERR)
status = STATUS_RC522_TEMP_ERROR; /* Temperature Error */
if(getRegVal & JBIT_WRERR)
status = STATUS_FIFO_WRITE_ERROR; /* Error Writing to FIFO */
if(status == STATUS_SUCCESS)
status = STATUS_ERROR_NY_IMPLEMENTED; /* Error not yet implemented, shall never occur! */
/* if an error occured, clear error register before IRQ register */
RcSetReg(JREG_ERROR, 0);
}
/*read data from FIFO and set response parameter*/
if(status != STATUS_ACK_SUPPOSED)
{
// for(i=0; i<MpIsrInfo->nBytesReceived; i++)
//{
// ExchangeBuf[i] = RcGetReg(JREG_FIFODATA);
//}
ReadFIFO(ExchangeBuf,MInfo.nBytesReceived);
/*in case of incomplete last byte reduce number of complete bytes by 1*/
if(MInfo.nBitsReceived && MInfo.nBytesReceived)
MInfo.nBytesReceived --;
}
}
RcSetReg(JREG_COMMIRQ, waitForComm);
RcSetReg(JREG_DIVIRQ, waitForDiv);
RcSetReg(JREG_FIFOLEVEL, JBIT_FLUSHBUFFER);
RcSetReg(JREG_COMMIRQ, JBIT_TIMERI);
RcSetReg(JREG_BITFRAMING, 0);
return status;
}
/****************************************************************************************
** 函数原型: char PiccRequest(unsigned char req_code, unsigned char idata *atq);
** 函数功能: 请求天线感应区内的卡
** 入口参数: unsigned char req_code ; 请求类型 REQALL、REQIDLE
** 出口参数: unsigned char idata *atq ; 请求回应
** 返 回 值: -
** 描 述: 请求回应的代码
** MF0 IC U1 的类型号:0044H
** MF1 IC S50 的类型号:0004H
** MF1 IC S70 的类型号:0002H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -