RFID MFRC522

Schéma d’Ensemble

ensemble_mfrc522.svg


Documents

vma405 datasheet

mfrc522_datasheet


Projet Démonstration

WORKSPACE_F411_RFID_MFRC522.zip

code RFID

rfid.h

/*
 * rfid.h
 *
 *  Created on: Sep 6, 2017
 *      Author: kerhoas
 */

#ifndef INC_RFID_H_
#define INC_RFID_H_

#include "main.h"

#define MAX_LEN 16  // Maximum length of the array

// MF522 command word
#define PCD_IDLE              0x00               //NO action; cancel the current command
#define PCD_AUTHENT           0x0E               // authentication key
#define PCD_RECEIVE           0x08               // receive data
#define PCD_TRANSMIT          0x04               // Transmit Data
#define PCD_TRANSCEIVE        0x0C               // Send and receive data
#define PCD_RESETPHASE        0x0F               // Reset
#define PCD_CALCCRC           0x03               // CRC calculation

// Mifare_One card command word
#define PICC_REQIDL           0x26               // find the antenna area does not enter hibernation
#define PICC_REQALL           0x52               // find all the cards antenna area
#define PICC_ANTICOLL         0x93               // anti-collision
#define PICC_SElECTTAG        0x93               // election card
#define PICC_AUTHENT1A        0x60               // authentication key A
#define PICC_AUTHENT1B        0x61               // authentication key B
#define PICC_READ             0x30               // Read Block
#define PICC_WRITE            0xA0               // write block
#define PICC_DECREMENT        0xC0               // debit?
#define PICC_INCREMENT        0xC1               // recharge?
#define PICC_RESTORE          0xC2               // transfer block data to the buffer
#define PICC_TRANSFER         0xB0               // save the data in the buffer
#define PICC_HALT             0x50               // Sleep

// MF522 communication error code is returned when
#define MI_OK                 0
#define MI_NOTAGERR           1
#define MI_ERR                2

//======================================================================================
//								MFRC522 register
//======================================================================================
//Page 0:Command and Status
#define     Reserved00            0x00
#define     CommandReg            0x01
#define     CommIEnReg            0x02
#define     DivlEnReg             0x03
#define     CommIrqReg            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     Reserved01            0x0F
//Page 1:Command
#define     Reserved10            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     Reserved11            0x1A
#define     Reserved12            0x1B
#define     MifareReg             0x1C
#define     Reserved13            0x1D
#define     Reserved14            0x1E
#define     SerialSpeedReg        0x1F
//Page 2:CFG
#define     Reserved20            0x20
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     Reserved21            0x23
#define     ModWidthReg           0x24
#define     Reserved22            0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsPReg            0x28
#define     ModGsPReg             0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
//Page 3:TestRegister
#define     Reserved30            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     Reserved31            0x3C
#define     Reserved32            0x3D
#define     Reserved33            0x3E
#define     Reserved34        	  0x3F
//======================================================================================
void RFID_powerOn(void);
bool RFID_isCard();
bool RFID_readCardSerial();
void RFID_init();
void RFID_reset();
void RFID_writeMFRC522(uint8_t addr, uint8_t val);
void RFID_antennaOn(void);
uint8_t RFID_readMFRC522(uint8_t addr);
void RFID_setBitMask(uint8_t reg, uint8_t mask);
void RFID_clearBitMask(uint8_t reg, uint8_t mask);
void RFID_calculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData);
uint8_t RFID_MFRC522Request(uint8_t reqMode, uint8_t *TagType);
uint8_t RFID_MFRC522ToCard(uint8_t command, uint8_t *sendData, uint8_t sendLen, uint8_t *backData, uint32_t *backLen);
uint8_t RFID_anticoll(uint8_t *serNum);
uint8_t RFID_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum);
uint8_t RFID_readBlock(uint8_t blockAddr, uint8_t *recvData);
uint8_t RFID_writeBlock(uint8_t blockAddr, uint8_t *writeData);
void RFID_halt();

uint8_t serNum[5];       
uint8_t AserNum[5];     

//======================================================================================















#endif /* INC_RFID_H_ */

rfid.c

/******************************************************************************
 * Includes
 ******************************************************************************/

#include "rfid.h"

//===================================================================================
void RFID_powerOn(void)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);		// SPI DISABLE
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, 1);		// POWERDOWN OFF
}
//===================================================================================
 bool RFID_isCard()
 {
	uint8_t status;
	uint8_t str[MAX_LEN];

	status = RFID_MFRC522Request(PICC_REQIDL, str);
    if (status == MI_OK)  { return true; } else  { return false;}
 }
 //===================================================================================
 bool RFID_readCardSerial(){

	uint8_t status;
	uint8_t str[MAX_LEN];

	// Anti-collision, return card serial number 4 bytes
	status = RFID_anticoll(str);
	memcpy(serNum, str, 5);

    if (status == MI_OK)  { return true; } else  { return false;}
 }
//===================================================================================

void RFID_init()
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, 1);

	RFID_reset();

	//Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
    RFID_writeMFRC522(TModeReg, 0x8D);		//Tauto=1; f(Timer) = 6.78MHz/TPreScaler
    RFID_writeMFRC522(TPrescalerReg, 0x3E);	//TModeReg[3..0] + TPrescalerReg
    RFID_writeMFRC522(TReloadRegL, 30);
    RFID_writeMFRC522(TReloadRegH, 0);

	RFID_writeMFRC522(TxAutoReg, 0x40);		//100%ASK
	RFID_writeMFRC522(ModeReg, 0x3D);		// CRC initial value : 0x6363

	//RFID_clearBitMask(Status2Reg, 0x08);	//MFCrypto1On=0
	//RFID_writeMFRC522(RxSelReg, 0x86);	//RxWait = RxSelReg[5..0]
	//RFID_writeMFRC522(RFCfgReg, 0x7F);   	//RxGain = 48dB
	RFID_antennaOn();
}
//===================================================================================
void RFID_reset()
{
	RFID_writeMFRC522(CommandReg, PCD_RESETPHASE);
}
//===================================================================================
void RFID_writeMFRC522(uint8_t addr, uint8_t val)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
	spi1Transfer((addr<<1)&0x7E); 			// Address Format :0XXXXXX0
	spi1Transfer(val);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
}
//===================================================================================
void RFID_antennaOn(void)
{
	uint8_t temp;

	temp = RFID_readMFRC522(TxControlReg);
	if (!(temp & 0x03))
	{
		RFID_setBitMask(TxControlReg, 0x03);
	}
}
//===================================================================================
uint8_t RFID_readMFRC522(uint8_t addr)
{
	uint8_t val;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
	spi1Transfer(((addr<<1)&0x7E) | 0x80);   	// Address Format :1XXXXXX0
	val = spi1Transfer(0x00); 					// push ('write to read')
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
	return val;
}
//===================================================================================
void RFID_setBitMask(uint8_t reg, uint8_t mask)
{
    uint8_t tmp;
    tmp = RFID_readMFRC522(reg);
    RFID_writeMFRC522(reg, tmp | mask);  // set bit mask
}
//===================================================================================
void RFID_clearBitMask(uint8_t reg, uint8_t mask)
{
    uint8_t tmp;
    tmp = RFID_readMFRC522(reg);
    RFID_writeMFRC522(reg, tmp & (~mask));  // clear bit mask
}
//===================================================================================
/*
 * Function Name : CalulateCRC
 * Description: CRC calculation with MF522
 * Input parameters : pIndata - To read the CRC data , len - the data length , pOutData - CRC calculation results
 * Return value: None
 */
void RFID_calculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData)
{
    uint8_t i, n;

    RFID_clearBitMask(DivIrqReg, 0x04);			//CRCIrq = 0
    RFID_setBitMask(FIFOLevelReg, 0x80);		// FIFO
    //Write_MFRC522(CommandReg, PCD_IDLE);

    // Write data to the FIFO
    for (i=0; i<len; i++)
    {
		RFID_writeMFRC522(FIFODataReg, *(pIndata+i));
	}
    RFID_writeMFRC522(CommandReg, PCD_CALCCRC);

    // Read the CRC calculation result
    i = 0xFF;
    do
    {
        n = RFID_readMFRC522(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));			//CRCIrq = 1

    // Read the CRC calculation result
    pOutData[0] = RFID_readMFRC522(CRCResultRegL);
    pOutData[1] = RFID_readMFRC522(CRCResultRegM);
}
//===================================================================================
/*
 * Function Name : RFID_MFRC522ToCard
 * Description : RC522 and ISO14443 card communication
 * Input Parameters : command - MF522 command word,
 * SendData - RC522 sent to the card via the data
 * SendLen - length of data sent
 * BackData - received the card returns data,
 * BackLen - return data bit length
 * Return value: the successful return MI_OK
 */
uint8_t RFID_MFRC522ToCard(uint8_t command, uint8_t *sendData, uint8_t sendLen, uint8_t *backData, uint32_t *backLen)
{
    uint8_t status = MI_ERR;
    uint8_t irqEn = 0x00;
    uint8_t waitIRq = 0x00;
	uint8_t lastBits;
    uint8_t n;
    uint32_t i;

    switch (command)
    {
        case PCD_AUTHENT:		// certification cards close
		{
			irqEn = 0x12;
			waitIRq = 0x10;
			break;
		}
		case PCD_TRANSCEIVE:	// transmit FIFO data
		{
			irqEn = 0x77;
			waitIRq = 0x30;
			break;
		}
		default:
			break;
    }

    RFID_writeMFRC522(CommIEnReg, irqEn|0x80);	// enable interrupt request
    RFID_clearBitMask(CommIrqReg, 0x80);		// clear all interrupt request bit
    RFID_setBitMask(FIFOLevelReg, 0x80);		// FlushBuffer = 1, FIFO initialization

	RFID_writeMFRC522(CommandReg, PCD_IDLE);	 // NO action --> cancel the current command

	// Write data to the FIFO
    for (i=0; i<sendLen; i++)
    {
		RFID_writeMFRC522(FIFODataReg, sendData[i]);
	}

    // Execute the command
	RFID_writeMFRC522(CommandReg, command);
    if (command == PCD_TRANSCEIVE)
    {
		RFID_setBitMask(BitFramingReg, 0x80);		//StartSend=1,transmission of data starts
	}

    // Wait for completion of receiving data
	i = 2000;	// i according to the clock frequency adjustment , the operator M1 card maximum waiting time 25ms???
    do
    {
		//CommIrqReg[7..0]
		//Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
        n = RFID_readMFRC522(CommIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitIRq));

    RFID_clearBitMask(BitFramingReg, 0x80);			//StartSend=0

    if (i != 0)
    {
        if(!(RFID_readMFRC522(ErrorReg) & 0x1B))	//BufferOvfl Collerr CRCErr ProtecolErr
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {
				status = MI_NOTAGERR;
			}

            if (command == PCD_TRANSCEIVE)
            {
               	n = RFID_readMFRC522(FIFOLevelReg);
              	lastBits = RFID_readMFRC522(ControlReg) & 0x07;
                if (lastBits)
                {
					*backLen = (n-1)*8 + lastBits;
				}
                else
                {
					*backLen = n*8;
				}

                if (n == 0)
                {
					n = 1;
				}
                if (n > MAX_LEN)
                {
					n = MAX_LEN;
				}

                // Read the received data in FIFO
                for (i=0; i<n; i++)
                {
					backData[i] = RFID_readMFRC522(FIFODataReg);
				}
            }
        }
        else
        {
			status = MI_ERR;
		}

    }

    //RFID_setBitMask(ControlReg,0x80);           //timer stops
    //Write_MFRC522(CommandReg, PCD_IDLE);

    return status;
}

//===================================================================================
/*
 * Function Name : MFRC522_Request
 * Description : Find cards , read the card type number
 * Input parameters : reqMode - find cards way
 * TagType - Return Card Type
 * 0x4400 = Mifare_UltraLight
 * 0x0400 = Mifare_One (S50)
 * 0x0200 = Mifare_One (S70)
 * 0x0800 = Mifare_Pro (X)
 * 0x4403 = Mifare_DESFire
 * Return value: the successful return MI_OK
 */
uint8_t  RFID_MFRC522Request(uint8_t reqMode, uint8_t *TagType)
{
	uint8_t status;
	uint32_t backBits;			// received data bits

	RFID_writeMFRC522(BitFramingReg, 0x07);		//TxLastBists = BitFramingReg[2..0]

	TagType[0] = reqMode;
	status = RFID_MFRC522ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);

	if ((status != MI_OK) || (backBits != 0x10))
	{
		status = MI_ERR;
	}

	return status;
}
//===================================================================================
/**
 * Function Name : RFID_anticoll
 * Description : Anti- collision detection , reading selected card serial number card
 * Input parameters : serNum - returns 4 bytes card serial number , the first 5 bytes for the checksum byte
 * Return value: the successful return MI_OK
 */
uint8_t RFID_anticoll(uint8_t *serNum)
{
    uint8_t status;
    uint8_t i;
	uint8_t serNumCheck=0;
    uint32_t unLen;

    //RFID_clearBitMask(Status2Reg, 0x08);		//TempSensclear
    //RFID_clearBitMask(CollReg,0x80);			//ValuesAfterColl
	RFID_writeMFRC522(BitFramingReg, 0x00);		//TxLastBists = BitFramingReg[2..0]

    serNum[0] = PICC_ANTICOLL;
    serNum[1] = 0x20;
    status = RFID_MFRC522ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);

    if (status == MI_OK)
	{
    	// Check Card Serial Number
		for (i=0; i<4; i++)
		{
		 	serNumCheck ^= serNum[i];
		}
		if (serNumCheck != serNum[i])
		{
			status = MI_ERR;
		}
    }

    //RFID_setBitMask(CollReg, 0x80);		//ValuesAfterColl=1
    return status;
}
//===================================================================================
/*
 * Function Name : RFID_auth
 * Description : Verify card password
 * Input parameters : authMode - Password Authentication Mode
                 0x60 = A key authentication
                 0x61 = B key authentication
             BlockAddr - block address
             Sectorkey - Sector password
             serNum - card serial number, 4-byte
 * Return value: the successful return MI_OK
 */
uint8_t RFID_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum)
{
    uint8_t status;
    uint32_t recvBits;
    uint8_t i;
	uint8_t buff[12];

	// Validate instruction block address + sector + password + card serial number
    buff[0] = authMode;
    buff[1] = BlockAddr;
    for (i=0; i<6; i++)
    {
		buff[i+2] = *(Sectorkey+i);
	}
    for (i=0; i<4; i++)
    {
		buff[i+8] = *(serNum+i);
	}
    status = RFID_MFRC522ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);

    if ((status != MI_OK) || (!(RFID_readMFRC522(Status2Reg) & 0x08)))
    {
		status = MI_ERR;
	}

    return status;
}
//===================================================================================
/*
 * Function Name : RFID_readBlock
 * Description : Read block data
 * Input parameters : blockAddr - block address ; recvData - read block data
 * Return value: the successful return MI_OK
 */
uint8_t RFID_readBlock(uint8_t blockAddr, uint8_t *recvData)
{
    uint8_t status;
    uint32_t unLen;

    recvData[0] = PICC_READ;
    recvData[1] = blockAddr;
    RFID_calculateCRC(recvData,2, &recvData[2]);
    status = RFID_MFRC522ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);

    if ((status != MI_OK) || (unLen != 0x90))
    {
        status = MI_ERR;
    }

    return status;
}
//===================================================================================
/*
 * Function Name :  RFID_writeBlock
 * Description : Write block data
 * Input parameters : blockAddr - block address ; writeData - to 16-byte data block write
 * Return value: the successful return MI_OK
 */
uint8_t RFID_writeBlock(uint8_t blockAddr, uint8_t *writeData)
{
    uint8_t status;
    uint32_t recvBits;
    uint8_t i;
	uint8_t buff[18];

    buff[0] = PICC_WRITE;
    buff[1] = blockAddr;
    RFID_calculateCRC(buff, 2, &buff[2]);
    status = RFID_MFRC522ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);

    if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
    {
		status = MI_ERR;
	}

    if (status == MI_OK)
    {
        for (i=0; i<16; i++)		// FIFO 16 bytes
        {
        	buff[i] = *(writeData+i);
        }
        RFID_calculateCRC(buff, 16, &buff[16]);
        status = RFID_MFRC522ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);

		if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
        {
			status = MI_ERR;
		}
    }

    return status;
}

//===================================================================================
/*
 * Function Name : RFID_halt
 * Description : Command card into hibernation
 * Input: None
 * Return value: None
 */
void RFID_halt()
{
    uint32_t unLen;
    uint8_t buff[4];

    buff[0] = PICC_HALT;
    buff[1] = 0;
    RFID_calculateCRC(buff, 2, &buff[2]);

    RFID_MFRC522ToCard(PCD_TRANSCEIVE, buff, 4, buff,&unLen);
}
//===================================================================================
//							END OF FILE
//===================================================================================

main_mfrc522.c

#include "main.h"
#include "rfid.h"

int cards[][5] = {{117, 222, 140, 171, 140},{163, 134, 92, 178, 203}};
bool acces = false ;
extern uint8_t rec_buf2[NB_CAR_TO_RECEIVE+1];	 // defined in drv_uart.c

//=========================================================
//	>>>>>>>>>>>>	MAIN	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//=========================================================

int main(void)
{
HAL_Init();
SystemClock_Config();
uart2_Init();
spi1Init();

RFID_powerOn();
HAL_Delay(500);

RFID_init();

while(1)
{
	if( RFID_isCard() )
	{
		if(RFID_readCardSerial())
		{
			  term_printf("SERIAL NUMBER : %d %d %d %d %d \n\r", serNum[0],serNum[1],serNum[2],serNum[3],serNum[4]);

    	      for ( uint8_t x = 0; x < sizeof(cards); x++)
    	      {
    	        for (uint8_t i = 0; i < sizeof(serNum); i++ )
    	        {
    	          if (serNum[i] != cards[x][i])
    	          {
    	            acces = false;
    	            break;
    	          }
    	          else
    	          {
    	            acces = true;
    	          }
    	        }
    	        if (acces) break;
    	      }

    	    }
	}

	if (acces)
	{
		term_printf(" WELCOME \n\r");
		HAL_Delay(3000);
		acces = false;
	}
	else
	{

	}

	HAL_Delay(200);

	RFID_halt();

}  // END WHILE

return 0;
}

//=================================================================
//	UART RECEIVE CALLBACK5
//=================================================================
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
	if(UartHandle -> Instance == USART2)
	{
		 HAL_UART_Receive_IT(&Uart2Handle, (uint8_t *)rec_buf2, NB_CAR_TO_RECEIVE);
	}

}