前陣子太忙沒空把很久之前的東西記錄下來,趁現在有空紀錄一下

該篇針對RC522進行讀寫Mifare白卡做一個實驗記錄,要注意RFID有很多種協議並不是卡片靠近就一定能讀取或寫入,我們這邊以協議:ISO1443A的卡片作為範例

基本上去賣場Mifare就可以找到了,協議基本上都是ISO1443A,但買之前最好還是確認一下,另外就是RFID的IC也要確認是否有支援你所要用的協議

 

範例是使用UNO來做的,請先依照下面說明將線接好

UNO   RC522

 9        RST
10       SDA(SS)
11       MOSI
12       MISO
13       SCK

 

以下是讀取的程式碼

/*
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
 */

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
  Serial.begin(115200);   // Initialize serial communications with the PC
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  delay(4);       // Optional delay. Some board do need more time after init to be ready, see Readme
  mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
  Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  // Dump debug info about the card; PICC_HaltA() is automatically called
  mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
  delay(1500);
}

 

卡片靠近後,在監控視窗就可以看到卡片讀取出來的全部訊息了

Arduino-使用RC522讀寫Mifare白卡(協議:I

 

Arduino-使用RC522讀寫Mifare白卡(協議:I

Arduino-使用RC522讀寫Mifare白卡(協議:I

那網路上常講所謂的UID指的就是扇區0裡面的第0列的前四個也就是 EF 78 89 AE

 

接下來是寫入的程式碼,該範例會先寫入,再重新讀取,然後顯示出來

 

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN   9     // MFRC522的复位引脚
#define SS_PIN    10    // MFRC522的SPI SS引脚

MFRC522 mfrc522(SS_PIN, RST_PIN);   // 创建MFRC522实例

/* 设置新的UID */
#define NEW_UID {0xEF, 0x87, 0x79, 0xEE}

MFRC522::MIFARE_Key key;  // 储存密钥

byte sector = 15;   // 指定读写的扇区,可能值:0~15
byte block = 1;     // 指定读写的块,可能值:0~3
byte blockData[16] = "ssssskkkkkbbbbbb";   // 最多可存入16个字节的数据

void setup() {
  Serial.begin(115200);  // 初始化串口通信
  while (!Serial);     // 如果没有打开串口端口,则不执行任何操作(针对基于ATMEGA32U4的Arduino)
  SPI.begin();         // 初始化SPI总线
  mfrc522.PCD_Init();  // 初始化MFRC522卡片
  Serial.println(F("Warning: this example overwrites the UID of your UID changeable card, use with care!"));
  
  // 准备密钥 - 出厂时所有密钥都设置为FFFFFFFFFFFFh。
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

//
void writeBlock(byte _sector, byte _block, byte _blockData[]) {
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3) {
    // 显示「區段或區塊碼錯誤」,然後結束函式。
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  if (_sector == 0 && _block == 0) {
    // 显示「第一個區塊只能讀取」,然後結束函式。
    Serial.println(F("First block is read-only."));
    return;
  }

  byte blockNum = _sector * 4 + _block;  // 計算區塊的實際編號(0~63)
  byte trailerBlock = _sector * 4 + 3;   // 控制區塊編號

  // 驗證金鑰
  MFRC522::StatusCode status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  // 若未通過驗證…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 在指定區塊寫入16位元組資料
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockNum, _blockData, 16);
  // 若寫入不成功…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 顯示「寫入成功!」
  Serial.println(F("Data was written."));
}

void readBlock(byte _sector, byte _block, byte _blockData[])  {
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3) {
    // 顯示「區段或區塊碼錯誤」,然後結束函式。
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  byte blockNum = _sector * 4 + _block;  // 計算區塊的實際編號(0~63)
  byte trailerBlock = _sector * 4 + 3;   // 控制區塊編號

  // 驗證金鑰
  MFRC522::StatusCode status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  // 若未通過驗證…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  byte buffersize = 18;
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockNum, _blockData, &buffersize);

  // 若讀取不成功…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("MIFARE_read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 顯示「讀取成功!」
  Serial.println(F("Data was read."));
}

//

void loop() {
  // 重置循环如果传感器/读卡器上没有新卡。当空闲时,这会节省整个过程。如果有卡,选择一张。
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    delay(50);
    return;
  }
  
  // 现在已选择一张卡。UID和SAK在mfrc522.uid中。
  
  // 显示UID
  Serial.print(F("Card UID:"));
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
  } 
  Serial.println();

  // 设置新的UID
  byte newUid[] = NEW_UID;
  if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
    Serial.println(F("Wrote new UID to card."));
  }
  
  // Halt PICC and re-select it so DumpToSerial doesn't get confused
  mfrc522.PICC_HaltA();
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    return;
  }
  
 
  
  // 读取并写入卡片数据
  writeBlock(sector, block, blockData);
  readBlock(sector, block, blockData);  // 可以选择读取已写入的数据进行验证

   // 显示新的UID和内容
  Serial.println(F("New UID and contents:"));
  mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
  
  delay(2000);
}

 

下圖就是程式碼中修改資料的地方

Arduino-使用RC522讀寫Mifare白卡(協議:I

 

以下是修改完後的結果,可以看到我在扇區15跟0的資料及UID已經成功寫入了

Arduino-使用RC522讀寫Mifare白卡(協議:I

Arduino-使用RC522讀寫Mifare白卡(協議:I

 

 

 

arrow
arrow
    創作者介紹
    創作者 凶王 的頭像
    凶王

    凶王的部落

    凶王 發表在 痞客邦 留言(0) 人氣()