⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mifare.c

📁 RC522完整源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* /////////////////////////////////////////////////////////////////////////////////////////////////
//                     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 + -