Arduino MFRC522
Digital 10 ----> SDA
Digital 11(MOSI) ----> MOSI(DI)
Digital 12(MISO) ----> MISO(DO)
Digital 13(SCK) ----> SCLK(CK)
Digital 5 ----> RST
Digital 5 ----> RST
VCC 3.3V ----> VCC
GND ----> GND
MFRC522.h
#ifndef __MFRC522__
#define __MFRC522__
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <SPI.h>
//data array maxium length
const unsigned int MAX_LEN = 16;
//MFRC522 command bits
const unsigned char PCD_IDLE = 0x00; //NO action; cancel current commands
const unsigned char PCD_AUTHENT = 0x0E; //verify password key
const unsigned char PCD_RECEIVE = 0x08; //receive data
const unsigned char PCD_TRANSMIT = 0x04; //send data
const unsigned char PCD_TRANSCEIVE = 0x0C; //send and receive data
const unsigned char PCD_RESETPHASE = 0x0F; //reset
const unsigned char PCD_CALCCRC = 0x03; //CRC check and caculation
//Mifare_One card command bits
const unsigned char PICC_REQIDL = 0x26; //Search the cards that not into sleep mode in the antenna area
const unsigned char PICC_REQALL = 0x52; //Search all the cards in the antenna area
const unsigned char PICC_ANTICOLL = 0x93; //prevent conflict
const unsigned char PICC_SElECTTAG = 0x93; //select card
const unsigned char PICC_AUTHENT1A = 0x60; //verify A password key
const unsigned char PICC_AUTHENT1B = 0x61; //verify B password key
const unsigned char PICC_READ = 0x30; //read
const unsigned char PICC_WRITE = 0xA0; //write
const unsigned char PICC_DECREMENT = 0xC0; //deduct value
const unsigned char PICC_INCREMENT = 0xC1; //charge up value
const unsigned char PICC_RESTORE = 0xC2; //Restore data into buffer
const unsigned char PICC_TRANSFER = 0xB0; //Save data into buffer
const unsigned char PICC_HALT = 0x50; //sleep mode
//THe mistake code that return when communicate with MFRC522
const unsigned char MI_OK = 0;
const unsigned char MI_NOTAGERR = 1;
const unsigned char MI_ERR = 2;
//------------------MFRC522 register ---------------
//Page 0:Command and Status
const unsigned char Reserved00 = 0x00;
const unsigned char CommandReg = 0x01;
const unsigned char CommIEnReg = 0x02;
const unsigned char DivlEnReg = 0x03;
const unsigned char CommIrqReg = 0x04;
const unsigned char DivIrqReg = 0x05;
const unsigned char ErrorReg = 0x06;
const unsigned char Status1Reg = 0x07;
const unsigned char Status2Reg = 0x08;
const unsigned char FIFODataReg = 0x09;
const unsigned char FIFOLevelReg = 0x0A;
const unsigned char WaterLevelReg = 0x0B;
const unsigned char ControlReg = 0x0C;
const unsigned char BitFramingReg = 0x0D;
const unsigned char CollReg = 0x0E;
const unsigned char Reserved01 = 0x0F;
//Page 1:Command
const unsigned char Reserved10 = 0x10;
const unsigned char ModeReg = 0x11;
const unsigned char TxModeReg = 0x12;
const unsigned char RxModeReg = 0x13;
const unsigned char TxControlReg = 0x14;
const unsigned char TxAutoReg = 0x15;
const unsigned char TxSelReg = 0x16;
const unsigned char RxSelReg = 0x17;
const unsigned char RxThresholdReg = 0x18;
const unsigned char DemodReg = 0x19;
const unsigned char Reserved11 = 0x1A;
const unsigned char Reserved12 = 0x1B;
const unsigned char MifareReg = 0x1C;
const unsigned char Reserved13 = 0x1D;
const unsigned char Reserved14 = 0x1E;
const unsigned char SerialSpeedReg = 0x1F;
//Page 2:CFG
const unsigned char Reserved20 = 0x20;
const unsigned char CRCResultRegM = 0x21;
const unsigned char CRCResultRegL = 0x22;
const unsigned char Reserved21 = 0x23;
const unsigned char ModWidthReg = 0x24;
const unsigned char Reserved22 = 0x25;
const unsigned char RFCfgReg = 0x26;
const unsigned char GsNReg = 0x27;
const unsigned char CWGsPReg = 0x28;
const unsigned char ModGsPReg = 0x29;
const unsigned char TModeReg = 0x2A;
const unsigned char TPrescalerReg = 0x2B;
const unsigned char TReloadRegH = 0x2C;
const unsigned char TReloadRegL = 0x2D;
const unsigned char TCounterValueRegH = 0x2E;
const unsigned char TCounterValueRegL = 0x2F;
//Page 3:TestRegister
const unsigned char Reserved30 = 0x30;
const unsigned char TestSel1Reg = 0x31;
const unsigned char TestSel2Reg = 0x32;
const unsigned char TestPinEnReg = 0x33;
const unsigned char TestPinValueReg = 0x34;
const unsigned char TestBusReg = 0x35;
const unsigned char AutoTestReg = 0x36;
const unsigned char VersionReg = 0x37;
const unsigned char AnalogTestReg = 0x38;
const unsigned char TestDAC1Reg = 0x39;
const unsigned char TestDAC2Reg = 0x3A;
const unsigned char TestADCReg = 0x3B;
const unsigned char Reserved31 = 0x3C;
const unsigned char Reserved32 = 0x3D;
const unsigned char Reserved33 = 0x3E;
const unsigned char Reserved34 = 0x3F;
//-----------------------------------------------
class MFRC522
{
public:
MFRC522();
void Write(const unsigned char,const unsigned char);
unsigned char Read(const unsigned char);
void SetBitMask(const unsigned char,const unsigned char);
void ClearBitMask(const unsigned char,const unsigned char);
void AntennaOn();
void AntennaOff();
void Reset();
void Init();
unsigned char MFRC522ToCard(const unsigned char,
const unsigned char*,
const unsigned char,
unsigned char*,
unsigned int*);
unsigned char WriteBlock(unsigned char,unsigned char*);
unsigned char Request(unsigned char,unsigned char*);
unsigned char Anticoll(unsigned char*);
void CalulateCRC(unsigned char*,unsigned char,unsigned char*);
unsigned char SelectTag(unsigned char*);
void Halt();
private:
const static int chip_select_pin = 10;
const static int NRSTPD = 5;
};
#endif
MFRC522.cpp
#include <MFRC522.h>
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
MFRC522::MFRC522()
{
pinMode(chip_select_pin,OUTPUT);
digitalWrite(chip_select_pin,LOW);
pinMode(NRSTPD,OUTPUT);
digitalWrite(NRSTPD,HIGH);
}
void MFRC522::Write(const unsigned char address,const unsigned char value)
{
digitalWrite(chip_select_pin,LOW);
SPI.transfer((address << 1) & 0x7E);
SPI.transfer(value);
digitalWrite(chip_select_pin,HIGH);
}
unsigned char MFRC522::Read(const unsigned char address)
{
unsigned char value;
digitalWrite(chip_select_pin,LOW);
SPI.transfer(((address << 1) & 0x7E) | 0x80);
value = SPI.transfer(0x00);
digitalWrite(chip_select_pin,HIGH);
return value;
}
void MFRC522::SetBitMask(const unsigned char reg,const unsigned char mask)
{
unsigned char temp;
temp = Read(reg);
Write(reg,temp | mask);
}
void MFRC522::ClearBitMask(const unsigned char reg,const unsigned char mask)
{
unsigned char temp;
temp = Read(reg);
Write(reg,temp & (~mask)); // clear bit mask
}
void MFRC522::AntennaOn()
{
unsigned char temp;
temp = Read(TxControlReg);
if(!(temp & 0x03)){
SetBitMask(TxControlReg,0x03);
}
}
void MFRC522::AntennaOff()
{
ClearBitMask(TxControlReg,0x03);
}
void MFRC522::Reset()
{
Write(CommandReg,PCD_RESETPHASE);
}
void MFRC522::Init()
{
Reset();
Write(TModeReg,0x8D);
Write(TPrescalerReg,0x3E);
Write(TReloadRegL,30);
Write(TReloadRegH,0);
Write(TxAutoReg,0x40);
Write(ModeReg,0x3D);
AntennaOn();
}
unsigned char MFRC522::MFRC522ToCard(const unsigned char command,const unsigned char *send_data,const unsigned char send_len,unsigned char *back_data,unsigned int *back_len)
{
unsigned char status = MI_ERR;
unsigned char irqEn = 0x00;
unsigned char waitIRq = 0x00;
unsigned char lastBits;
unsigned char n;
unsigned int i;
switch(command)
{
case PCD_AUTHENT: //verify card password
{
irqEn = 0x12;
waitIRq = 0x10;
break;
}
case PCD_TRANSCEIVE: //send data in the FIFO
{
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
}
Write(CommIEnReg,irqEn | 0x80); //Allow interruption
ClearBitMask(CommIrqReg,0x80); //Clear all the interrupt bits
SetBitMask(FIFOLevelReg,0x80); //FlushBuffer=1, FIFO initilizate
Write(CommandReg,PCD_IDLE); //NO action;cancel current command ???
//write data into FIFO
for (i = 0; i < send_len;++i){
Write(FIFODataReg,send_data[i]);
}
//procceed it
Write(CommandReg,command);
if (command == PCD_TRANSCEIVE){
SetBitMask(BitFramingReg,0x80); //StartSend=1,transmission of data starts
}
//waite receive data is finished
i = 2000; //i should adjust according the clock, the maxium the waiting time should be 25 ms???
do {
//CommIrqReg[7..0]
//Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = Read(CommIrqReg);
--i;
}
while ((i != 0) && !(n & 0x01) && !(n & waitIRq));
ClearBitMask(BitFramingReg,0x80); //StartSend=0
if (i != 0){
if(!(Read(ErrorReg) & 0x1B)){ //BufferOvfl Collerr CRCErr ProtecolErr
status = MI_OK;
if(n & irqEn & 0x01){
status = MI_NOTAGERR; //??
}
if(command == PCD_TRANSCEIVE){
n = Read(FIFOLevelReg);
lastBits = Read(ControlReg) & 0x07;
if (lastBits){
*back_len = (n - 1) * 8 + lastBits;
}
else{
*back_len = n*8;
}
if(n == 0){
n = 1;
}
if (n > MAX_LEN){
n = MAX_LEN;
}
//read the data from FIFO
for (i=0; i < n;++i){
back_data[i] = Read(FIFODataReg);
}
}
}
else{
status = MI_ERR;
}
}
//SetBitMask(ControlReg,0x80); //timer stops
//Write(CommandReg, PCD_IDLE);
return status;
}
unsigned char MFRC522::WriteBlock(unsigned char block_address,unsigned char *write_data)
{
unsigned char status;
unsigned int recvBits;
unsigned char i;
unsigned char buff[18];
buff[0] = PICC_WRITE;
buff[1] = block_address;
CalulateCRC(buff,2,&buff[2]);
status = 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){ //Write 16 bytes data into FIFO
buff[i] = *(write_data+i);
}
CalulateCRC(buff,16,&buff[16]);
status = MFRC522ToCard(PCD_TRANSCEIVE,buff,18,buff,&recvBits);
if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)){
status = MI_ERR;
}
}
return status;
}
unsigned char MFRC522::Request(unsigned char mode,unsigned char *tag_type)
{
unsigned char status;
unsigned int backBits; //the data bits that received
Write(BitFramingReg,0x07); //TxLastBists = BitFramingReg[2..0] ???
tag_type[0] = mode;
status = MFRC522ToCard(PCD_TRANSCEIVE,tag_type,1,tag_type,&backBits);
if ((status != MI_OK) || (backBits != 0x10)){
status = MI_ERR;
}
return status;
}
unsigned char MFRC522::Anticoll(unsigned char *uid)
{
unsigned char status;
unsigned char i;
unsigned char serNumCheck=0;
unsigned int unLen;
//ClearBitMask(Status2Reg, 0x08); //strSensclear
//ClearBitMask(CollReg,0x80); //ValuesAfterColl
Write(BitFramingReg,0x00); //TxLastBists = BitFramingReg[2..0]
uid[0] = PICC_ANTICOLL;
uid[1] = 0x20;
status = MFRC522ToCard(PCD_TRANSCEIVE,uid,2,uid,&unLen);
if (status == MI_OK){
//Verify card UID
for (i=0;i < 4;++i){
serNumCheck ^= uid[i];
}
if (serNumCheck != uid[i]){
status = MI_ERR;
}
}
//SetBitMask(CollReg, 0x80); //ValuesAfterColl=1
return status;
}
void MFRC522::CalulateCRC(unsigned char *input,unsigned char len,unsigned char *output)
{
unsigned char i,n;
ClearBitMask(DivIrqReg,0x04); //CRCIrq = 0
SetBitMask(FIFOLevelReg,0x80); //Clear FIFO pointer
//Write(CommandReg, PCD_IDLE);
//Write data into FIFO
for (i=0;i < len;i++){
Write(FIFODataReg,*(input + i));
}
Write(CommandReg,PCD_CALCCRC);
//waite CRC caculation to finish
i = 0xFF;
do {
n = Read(DivIrqReg);
--i;
}
while ((i != 0) && !(n & 0x04)); //CRCIrq = 1
//read CRC caculation result
output[0] = Read(CRCResultRegL);
output[1] = Read(CRCResultRegM);
}
unsigned char MFRC522::SelectTag(unsigned char *uid)
{
unsigned char i;
unsigned char status;
unsigned char size;
unsigned int recvBits;
unsigned char buffer[9];
//ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0
buffer[0] = PICC_SElECTTAG;
buffer[1] = 0x70;
for (i=0; i<5; i++){
buffer[i + 2] = *(uid + i);
}
CalulateCRC(buffer,7,&buffer[7]);
status = MFRC522ToCard(PCD_TRANSCEIVE,buffer,9,buffer,&recvBits);
if ((status == MI_OK) && (recvBits == 0x18)){
size = buffer[0];
}
else{
size = 0;
}
return size;
}
void MFRC522::Halt()
{
unsigned char status;
unsigned int unLen;
unsigned char buff[4];
buff[0] = PICC_HALT;
buff[1] = 0;
CalulateCRC(buff,2,&buff[2]);
status = MFRC522ToCard(PCD_TRANSCEIVE,buff,4,buff,&unLen);
}
8H10D.ino
#include <MFRC522.h>
#include <SPI.h>
/* 16^0 ~ 16^7 */
unsigned long table[8] = {1,16,256,4096,65536,1048576,16777216,268435456};
MFRC522 mfrc522;
unsigned char uid[5];
void setup()
{
Serial.begin(9600);
SPI.begin();
mfrc522.Init();
}
void loop()
{
unsigned char status;
unsigned char str[MAX_LEN];
status = mfrc522.Request(PICC_REQIDL,str);
if (status != MI_OK){
return;
}
status = mfrc522.Anticoll(str);
if (status == MI_OK){
memcpy(uid,str,5);
mfrc522.SelectTag(uid); //防止同張卡片持續感應與讀取
Serial.print("Original UID : ");
unsigned long sum = 0; //將UID每位byte加總(4byte uid & 1byte check)
for(int i = 3;i >= 0;--i){
unsigned long temp_h = (uid[i] >> 4) & 0x0000000F;
Serial.print(temp_h,HEX);
sum += (temp_h * table[(i*2)+1]); //加上UID每byte的高4bit
unsigned long temp_l = (uid[i] & 0x0000000F);
Serial.print(temp_l,HEX);
sum += (temp_l * table[i*2]); //加上UID每byte的低4bit
}
Serial.println("");
Serial.print("8H10D UID : ");
String _8H10D = String(sum);
if(_8H10D.length() < 10){
for(int i = 0;i < (10 - _8H10D.length());++i){
Serial.print("0"); //8H10D格式未滿十碼開頭補零
}
}
for(int i = 0;i < _8H10D.length();++i){
Serial.print(_8H10D.charAt(i));
}
}
Serial.println("");
mfrc522.Halt();
delay(100);
}
參考:
MFRC522 Datasheet
作者您好~ 感謝您這麼熱心提供RFID資料,不過有個疑惑請教一下,目前這個範例似乎無法感應悠遊卡,不知道是什麼原因呢? 謝謝
回覆刪除一定可以感應並讀取悠遊卡uid,如果你說的是內容有加密除非你...
回覆刪除作者您好,我也是卡在資料轉換直到看見您這篇文章
回覆刪除想請教是如何知道由UID轉8H10D是將byte倒序排列呢(有沒有線索可以得知?)
感謝您:)