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

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

在實驗的過程中讀取全部的資料是可行的,但在寫入方面有遇到扇區0(UID所屬的區塊)無法修改,其他區塊可以正常寫入的情形,不確定是否跟函式庫有關,或者是我哪裡疏忽了

 

這邊使用NANO作為範例,請照以下說明將線接好

NANO        PN532

VIN(5V)      VCC
GND           GND
A4              SDA
A5              SCL

 

以下為讀取的程式碼

//5V
//GND
//SDA -> A4
//SCL -> A5
#include <Wire.h>
#include <Adafruit_PN532.h>

#define PN532_IRQ   (2)
#define PN532_RESET (3)

Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

void setup(void) {
    Serial.begin(115200);
    while (!Serial) delay(10); // for Leonardo/Micro/Zero

    Serial.println("Looking for PN532...");

    nfc.begin();

    uint32_t versiondata = nfc.getFirmwareVersion();
    if (!versiondata) {
        Serial.print("Didn't find PN53x board");
        while (1); // halt
    }
  
    Serial.print("Found chip PN5"); 
    Serial.println((versiondata>>24) & 0xFF, HEX);
    Serial.print("Firmware ver. "); 
    Serial.print((versiondata>>16) & 0xFF, DEC);
    Serial.print('.'); 
    Serial.println((versiondata>>8) & 0xFF, DEC);

    Serial.println("Waiting for an ISO14443A Card ...");
}

void loop(void) {
    uint8_t success;
    uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
    uint8_t uidLength;
    uint8_t currentblock;
    bool authenticated = false;
    uint8_t data[16];

    uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

    success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);

    if (success) {
        Serial.println("Found an ISO14443A card");
        Serial.print("  UID Length: "); 
        Serial.print(uidLength, DEC);
        Serial.println(" bytes");
        Serial.print("  UID Value: ");
        nfc.PrintHex(uid, uidLength);
        Serial.println("");

        if (uidLength == 4)
        {
            Serial.println("Seems to be a Mifare Classic card (4 byte UID)");

            for (currentblock = 0; currentblock < 64; currentblock++)
            {
                if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false;

                if (!authenticated)
                {
                    Serial.print("------------------------Sector ");
                    Serial.print(currentblock/4, DEC);
                    Serial.println("-------------------------");

                    if (currentblock == 0)
                    {
                        success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
                    }
                    else
                    {
                        success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
                    }
                    if (success)
                    {
                        authenticated = true;
                    }
                    else
                    {
                        Serial.println("Authentication error");
                    }
                }
                if (!authenticated)
                {
                    Serial.print("Block ");
                    Serial.print(currentblock, DEC);
                    Serial.println(" unable to authenticate");
                }
                else
                {
                    success = nfc.mifareclassic_ReadDataBlock(currentblock, data);
                    if (success)
                    {
                        Serial.print("Block ");
                        Serial.print(currentblock, DEC);
                        Serial.print(" ");
                        for (int i = 0; i < 16; i++) {
                            if (data[i] < 0x10) {
                                Serial.print("0");
                            }
                            Serial.print(data[i], HEX);
                            Serial.print(" ");
                        }
                        Serial.println();
                    }
                    else
                    {
                        Serial.print("Block ");
                        Serial.print(currentblock, DEC);
                        Serial.println(" unable to read this block");
                    }
                }
            }
            
        }
        else
        {
            Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
        }
    }

    Serial.println("\n\n DONE");
    
    delay(2000);

}

 

下面為讀取到的卡片全部資料

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

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

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

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

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

 

接下來是寫入的程式碼,該範例會先讀取你卡片的UID在進行寫入資料,成功之後會顯示出成功的提示以及成功燒錄哪一個區塊

因為程式會一直偵測卡片是否有靠近IC,所以每隔幾秒當你沒有卡片靠近時就會跳出提示找不到卡片

 

#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>

PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);

void setup(void) {
  Serial.begin(115200);
  Serial.println("START!");

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (!versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }

  nfc.SAMConfig();
  Serial.println("Waiting for an NFC card ...");
}

void loop(void) {
  uint8_t success;
  uint8_t currentuid[7]; // Buffer to store the current UID
  uint8_t uidLength;

  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, currentuid, &uidLength);
  if (success) {
    Serial.println("Found an ISO14443A card!");

    Serial.print("Current UID: ");
    for (uint8_t i = 0; i < uidLength; i++) {
      Serial.print(currentuid[i], HEX);
      Serial.print(" ");
    }
    Serial.println("");

    // Authenticate with the card using the default key
    uint8_t keyA[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    success = nfc.mifareclassic_AuthenticateBlock(currentuid, uidLength, 4, 1, keyA);//block4-15

    if (success) {
      Serial.println("Authentication successful!");

      // Write the new UID to block 4
      uint8_t newUID[] = {0xCC, 0x88, 0x79, 0xAE, 0x83, 0x87, 0x66, 0x55, 0x33, 0x6F, 0x22, 0xDD, 0x86, 0xBB, 0xF8, 0x1D};
      success = nfc.mifareclassic_WriteDataBlock(4, newUID);

      if (success) {
        Serial.println("New UID successfully written to block 4!");
      } else {
        Serial.println("Failed to write new UID to block 4.");
      }
    } else {
      Serial.println("Authentication failed!");
    }
  } else {
    Serial.println("Didn't find an NFC card");
  }
  delay(1000);
}

 

下圖是程式碼中填入你想修改的BLOCK跟資料

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

下面是程式運作時的畫面

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

接著在燒回讀取的程式碼,讀區剛剛的卡片有沒有修改成功

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

現在可以看到BLOCK4確實已經成功的被修改了

 

 

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

    凶王的部落

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