該篇針對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);
}
下面為讀取到的卡片全部資料
接下來是寫入的程式碼,該範例會先讀取你卡片的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跟資料
下面是程式運作時的畫面
接著在燒回讀取的程式碼,讀區剛剛的卡片有沒有修改成功
現在可以看到BLOCK4確實已經成功的被修改了