17-RFID
模仿上文
Mifare讀寫器模組與Arduino接線示範
本單元使用的Mifare RFID-RC522讀寫器模組的外觀與接腳定義如下,模組採用的MFRC522晶片本身有支援UART, I2C和SPI介面,但是本文採用的程式庫僅支援SPI介面。
Arduino Uno板的接線示範如下,SPI介面的晶片線選擇通常接在Arduino數位10腳,但這不是強制性的,模組的Reset腳也可以接在其他腳位:
操控Mifare模組的MFRC522程式庫
本單元程式採用Miki Balboa開發的這個MFRC522程式庫來操控Mifare模組,若不使用程式庫,我們需要詳閱MFRC522晶片的規格書,了解讀寫器、卡片和微控制器之間的數據通訊流程,以及晶片內部的暫存器的指令位址,才能動手撰寫程式。
下載程式庫之後,請將它解壓縮到Arduino的libraries資料夾,再開啟Arduino IDE,即可從主功能表的「檔案→範例→MFRC522」指令底下找到一些範例程式。
底下列舉本單元使用到的MFRC522程式物件的方法和屬性:
MFRC522物件.PCD_Init():初始化MFRC522讀卡機模組
MFRC522物件.PICC_IsNewCardPresent():是否感應到新的卡片
MFRC522物件.PICC_ReadCardSerial():讀取卡片的資料
MFRC522物件.PICC_GetType():取得卡片類型
MFRC522物件.PICC_GetTypeName():取得卡片類型名稱
每張Mifare卡片都有個唯一的ID(unique identifier,簡稱UID),當讀寫機讀取到卡片的資料之後,UID的長度和內容,可從底下兩個屬性值取得:
MFRC522物件.uid.size:包含UID的長度
MFRC522物件.uid.uidByte:包含UID碼的陣列
讀取Mifare卡片的UID碼
讀取Mifare卡片的流程如下,我們的程式不需要理會其中的「防衝突處理」和「選卡」部份,讀寫器會幫我們搞定,但是在讀取資料之後,我們的程式要發出命令讓卡片進入停止(halt)狀態,避免讀寫器重複讀取同一張卡片:
SAK代表select acknowledge,直譯為「選擇應答」,是由卡片發給讀寫器,對於選擇卡片命令的回應,不同類型的Mifare卡片的SAK值不一樣(例如,Mifare Classic的SAK值為0x18),程式可藉此判別感應到的卡片類型。詳細的防衝突處理與SAK值判斷流程,請參閱NXP公司的“MIFARE ISO/IEC 14443 PICC Selection”技術文件(PDF格式)。
讀取Mifare卡片類型及其UID碼的程式如下:
#include <SPI.h>
#include <MFRC522.h> // 引用程式庫
#define RST_PIN A0 // 讀卡機的重置腳位
#define SS_PIN 10 // 晶片選擇腳位
MFRC522 mfrc522(SS_PIN, RST_PIN); // 建立MFRC522物件
void setup() {
Serial.begin(9600);
Serial.println("RFID reader is ready!");
SPI.begin();
mfrc522.PCD_Init(); // 初始化MFRC522讀卡機模組
}
void loop() {
// 確認是否有新卡片
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
byte *id = mfrc522.uid.uidByte; // 取得卡片的UID (第20行)
byte idSize = mfrc522.uid.size; // 取得UID的長度
Serial.print("PICC type: "); // 顯示卡片類型
// 根據卡片回應的SAK值(mfrc522.uid.sak)判斷卡片類型
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // (第25行)
Serial.println(mfrc522.PICC_GetTypeName(piccType));
Serial.print("UID Size: "); // 顯示卡片的UID長度值
Serial.println(idSize);
for (byte i = 0; i < idSize; i++) { // 逐一顯示UID碼
Serial.print("id[");
Serial.print(i);
Serial.print("]: ");
Serial.println(id[i], HEX); // 以16進位顯示UID值
}
Serial.println();
mfrc522.PICC_HaltA(); // 讓卡片進入停止模式
}
}
程式第20行宣告一個指向儲存UID值的指標變數(假設UID碼的長度為4):
第25行的“MFRC522::PICC_Type”代表引用在MFRC522類別(程式庫)裡面定義的PICC_Type這個資料類型,其中的雙冒號(::)代表範圍解析運算子(scope-resolution operator),用來表示“PICC_Type”定義在MFRC522程式庫裡面。如果不用雙冒號指出“PICC_Type”資料類型的來源,程式編譯器會產生未定義之類的錯誤。
上傳程式碼之後,開啟序列埠監控視窗,你可以嘗試一次讓Mifare模組感應多個卡片(筆者同時用3個),它將能逐一顯示每個卡片的類型和UID: