📄 mifare.c
字号:
/* /////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Philips Semiconductors
//
// All rights are reserved. Reproduction in whole or in part is
// prohibited without the written consent of the copyright owner.
// Philips reserves the right to make changes without notice at any time.
// Philips makes no warranty, expressed, implied or statutory, including but
// not limited to any implied warranty of merchantability or fitness for any
// particular purpose, or that the use will not infringe any third party patent,
// copyright or trademark. Philips must not be liable for any loss or damage
// arising from its use.
///////////////////////////////////////////////////////////////////////////////////////////////// */
/*! \file Mifare.c
*
* Project: Mifare reader with RC522
*
* Workfile: Mifare.c
* $Author: Bob Jiang $
* $Revision: 1.0 $
* $Date: Wed Aug 17 2005 $
*
* Comment:
* All the ISO14443-3 protocol and mifare command set are all implemented here.
* All the founctions in this file is totally independent of hardware.
* The source can be ported to other platforms very easily.
*
* The interrupt pin of the reader IC is not conntected and no interrupt needed.
* All protocol relevant timing constraints are generated
* by the internal timer of the reader module.
*
* Therefore the function M522PcdCmd is very important for understanding
* of the communication between reader and card.
*
*
* History:
*
*
*/
#include <string.h>
#include "RegCtrl.h"
#include "Rc522Reg.h"
#include "OpCtrl.h"
#include "ErrCode.h"
#include "Mifare.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;
#define ResetInfo(info) \
info.cmd = 0;\
info.status = STATUS_SUCCESS;\
info.nBytesSent = 0;\
info.nBytesToSend = 0;\
info.nBytesReceived = 0;\
info.nBitsReceived = 0;\
info.collPos = 0;
volatile MfCmdInfo MInfo;
volatile MfCmdInfo *MpIsrInfo = 0;
unsigned char idata SerBuffer[20];
/*************************************************
Function: SetPowerDown
Description:
set the rc522 enter or exit power down mode
Parameter:
ucFlag 0 -- exit power down mode
!0 -- enter power down mode
Return:
short status of implement
**************************************************/
void SetPowerDown(unsigned char ucFlag)
{
unsigned char RegVal;
/*
Note: The bit Power Down can not be set when the SoftReset command has been activated.
*/
if(ucFlag)
{
RegVal = RcGetReg(JREG_COMMAND); //enter power down mode
RegVal |= 0x10;
RcSetReg(JREG_COMMAND, RegVal);
}
else
{
RegVal = RcGetReg(JREG_COMMAND); //disable power down mode
RegVal &= (~0x10);
RcSetReg(JREG_COMMAND, RegVal);
}
}
/*************************************************
Function: SetTimeOut
Description:
Adjusts the timeout in 100us steps
Parameter:
uiMicroSeconds the time to set the timer(100us as a step)
Return:
short status of implement
**************************************************/
short SetTimeOut(unsigned int uiMicroSeconds)
{
unsigned int RegVal;
unsigned char TmpVal;
RegVal = uiMicroSeconds / 100;
/*
NOTE: The supported hardware range is bigger, since the prescaler here
is always set to 100 us.
*/
if(RegVal >= 0xfff)
{
return STATUS_INVALID_PARAMETER;
}
RcModifyReg(JREG_TMODE, 1, JBIT_TAUTO);
RcSetReg(JREG_TPRESCALER, 0xa6);
TmpVal = RcGetReg(JREG_TMODE);
TmpVal &= 0xf0;
TmpVal |= 0x02;
RcSetReg(JREG_TMODE, TmpVal);//82
RcSetReg(JREG_TRELOADLO, ((unsigned char)(RegVal&0xff)));
RcSetReg(JREG_TRELOADHI, ((unsigned char)((RegVal>>8)&0xff)));
return STATUS_SUCCESS;
}
/*************************************************
Function: ChangeJoinerBaudRate
Description:
Changes the serial speed of the RC522.
Note that the speed of the host interface (UART on PC) has to be also set to the
appropriate one.
Parameter:
baudrate new baudrate for rc522
Return:
short status of implement
**************************************************/
short ChangeJoinerBaudRate(unsigned long baudrate)
{
short status = STATUS_SUCCESS;
unsigned char setRegVal;
switch(baudrate)
{
case 9600:
setRegVal = 0xEB;
break;
case 14400:
setRegVal = 0xDA;
break;
case 19200:
setRegVal = 0xCB;
break;
case 38400:
setRegVal = 0xAB;
break;
case 57600:
setRegVal = 0x9A;
break;
case 115200:
setRegVal = 0x7A;
break;
case 128000:
setRegVal = 0x74;
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
/* Set the appropriate value */
if (status == STATUS_SUCCESS)
RcSetReg(JREG_SERIALSPEED,setRegVal);
/* Now the RC522 is set to the new speed*/
return status;
}
/*************************************************
Function: Rc522Init
Description:
initialize rc522 as a mifare reader
Parameter:
NONE
Return:
short status of implement
**************************************************/
void Rc522Init(void)
{
unsigned char RegVal;
RcSetReg(JREG_COMMAND, 0x0f); /*reset the RC522*/
/* disable Crypto1 bit*/
RcModifyReg(JREG_STATUS2, 0, JBIT_CRYPTO1ON);
/* do not touch bits: InvMod in register TxMode */
RegVal = RcGetReg(JREG_TXMODE);
RegVal = (unsigned char)(RegVal & JBIT_INVMOD);
RegVal = (unsigned char)(RegVal | JBIT_CRCEN | (RCO_VAL_RF106K << JOINER_SPEED_SHL_VALUE));
/* TxCRCEn = 1; TxSpeed = x; InvMod, TXMix = 0; TxFraming = 0 */
RcSetReg(JREG_TXMODE, RegVal);
/* do not touch bits: RxNoErr in register RxMode */
RegVal = RcGetReg(JREG_RXMODE);
RegVal = (unsigned char)(RegVal & JBIT_RXNOERR);
RegVal = (unsigned char)(RegVal | JBIT_CRCEN | (RCO_VAL_RF106K << JOINER_SPEED_SHL_VALUE));
/* RxCRCEn = 1; RxSpeed = x; RxNoErr, RxMultiple = 0; TxFraming = 0 */
RcSetReg(JREG_RXMODE, RegVal);
/* ADDIQ = 10b; FixIQ = 1; RFU = 0; TauRcv = 11b; TauSync = 01b */
RcSetReg(JREG_DEMOD, 0x6D);
/* RxGain = 4*/
RcSetReg(JREG_RFCFG, 0x48);
/* do settings common for all functions */
RcSetReg(JREG_RXTRESHOLD, 0x55); /* MinLevel = 5; CollLevel = 5 */
RcSetReg(JREG_MODWIDTH, 0x26); /* Modwidth = 0x26 */
RcSetReg(JREG_GSN, 0xF0 | 0x04); /* CWGsN = 0xF; ModGsN = 0x4 */
/* 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(5000);
/* 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);
/*
* Reset timer 1 ms using operation control commands (AutoMode and Prescaler are the same)
* set reload value
*/
SetTimeOut(5000);
RcSetReg(JREG_WATERLEVEL, 0x1A);
RcSetReg(JREG_TXSEL, 0x10);
RcSetReg(JREG_RXSEL, 0x84);
/* Activate receiver for communication
The RcvOff bit and the PowerDown bit are cleared, the command is not changed. */
RcSetReg(JREG_COMMAND, JCMD_IDLE);
/* Set timeout for REQA, ANTICOLL, SELECT to 200us */
SetTimeOut(2000);
}
/*************************************************
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:
short status of implement
**************************************************/
short M522PcdCmd(unsigned char cmd,
unsigned char *ExchangeBuf,
MfCmdInfo *info)
{
short status = STATUS_SUCCESS;
short istatus = 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;
unsigned int counter;
/*remove all Interrupt request flags that are used during function,
keep all other like they are*/
RcSetReg(JREG_COMMIRQ, waitForComm);
RcSetReg(JREG_DIVIRQ, 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);
}
MpIsrInfo = info;
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*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -