Mifare RFID-RC522模組實驗(一):讀取Mifare RFID卡的UID識別碼

本文旨在補充《超圖解Arduino互動設計入門》第18章「RFID無線識別裝置與問答遊戲製作」單元,書本採用的RFID讀卡機模組是採用9600bps, TTL序列通訊介面,RFID的通訊頻率為125KHz。這種模組的接線和程式都很簡單,每當感測到RFID卡,讀卡機就把卡片的識別碼送往序列埠。

市售Arduino套件裡面的RFID模組,多半是Mifare(讀音:my-fare)規格,跟書本的不一樣,因此本文將補充說明Mifare的基本原理及其模組的接線,以及讀取卡片識別碼的程式。

Mifare是NXP(恩智普)半導體公司推出的非接觸型IC卡(也就是外表沒有金屬接點的卡片),在市場上獲得廣泛的採用,像是停車場的感應幣(token)、現金卡(如:台灣的悠遊卡)、員工識別證…等等。Mifare卡有不同的系列,如:Mifare Classic, Mifare UltraLight, Mifare Pro…等,主要的差別在於資料安全加密和驗證的等級。

Mifare卡內建EEPROM,應用程式可對它寫入和讀取數據,例如:停車票卡可紀錄車主的停車時間。Mifare還具備「防衝突處理」機制,也就是避免訊號干擾:若多張卡片同時出現在偵測範圍,Mifare讀寫器將能逐一選擇卡片進行處理。例如,假設超級市場裡的每個商品都貼上RFID標籤,結帳櫃台的RFID讀取設備若具備防干擾機制,將能自動掃描堆放在購物推車裡的所有商品,結帳人員不必再手動逐一掃描商品條碼,也不會重複計算。附帶一提,所有符合ISO/IEC 14443-A標準規範的RFID卡片都要有防衝突處理功能,而Mifare是依循ISO/IEC 14443-A規格建立的非接觸式IC卡。

底下是Mifare裝置的概略圖,它的卡片屬於被動式、無內建電源(也稱為「無源」),卡片所需的電力來自讀寫器的電磁場。

Mifare裝置的概略圖

啟動RFID讀寫器之後,讀寫器的天線將不停地發送電磁波,每當卡片進入此電磁場,卡片內部的線圈和電路將與此電磁場產生共振,從而獲得電能。無線充電器也是透過電磁感應、非直接連線方式獲取能量,RFID讀寫器和卡片兩端的線圈(天線)相當於變壓器裡的主線圈和副線圈(請參閱「測試Palm Touchstone(點金石)無線充電模組」貼文。

依照感應距離,非接觸型IC卡分成緊耦合型(close-coupled,需要緊貼感測器)、接近式(proximity,10cm以內)和鄰近式(vicinity,50cm以內),Mifare屬於接近式,這種類型的卡片簡稱為PICC(Proximity IC Card,接近式IC卡),讀寫器則簡稱PCD(Proximity Coupling Device,接近型耦合器)。

另一方面,某些RFID的應用場合,標籤的尺寸大小有固定的標準,像信用卡和金融卡,這一類的卡片長、寬和厚度,都要遵循國際ID-1標準(85.6 × 53.98 × 0.76mm),目前的技術沒有辦法把電池塞入這麼薄的卡片,所以非接觸型卡片只能採用無線供電方案。

當卡片被電磁能啟動(activate)之後,將等待接收與回應來自讀寫器的命令。微控器和Mifare讀寫器之間採用TTL數位訊號傳遞資料,為了用電波傳送數位訊號,必須將數位訊號加上載波調變,Mifare的載波頻率是13.56MHz。上圖的射頻訊號波形只是描述概念,數位訊號在調變成電波之前,從讀寫器發送的訊號會採用米勒(Miller)編碼,而從卡片發出訊息則經過曼徹斯特(Manchester)編碼。讀寫器在操作卡片時,都會經過三次雙向認證,互相驗證使用的合法性,而且通訊過程中的所有數據都經過加密,以確保安全。

Mifare讀寫器模組與Arduino接線示範

本單元使用的Mifare RFID-RC522讀寫器模組的外觀與接腳定義如下,模組採用的MFRC522晶片本身有支援UART, I2C和SPI介面,但是本文採用的程式庫僅支援SPI介面。

Mifare RFID-RC522讀寫器模組

Arduino Uno板的接線示範如下,SPI介面的晶片線選擇通常接在Arduino數位10腳,但這不是強制性的,模組的Reset腳也可以接在其他腳位:

Mifare讀寫器模組與Arduino接線示範

操控Mifare模組的MFRC522程式庫

本單元程式採用Miki Balboa開發的這個MFRC522程式庫來操控Mifare模組,若不使用程式庫,我們需要詳閱MFRC522晶片的規格書,了解讀寫器、卡片和微控制器之間的數據通訊流程,以及晶片內部的暫存器的指令位址,才能動手撰寫程式。

下載程式庫之後,請將它解壓縮到Arduino的libraries資料夾,再開啟Arduino IDE,即可從主功能表的「檔案→範例→MFRC522」指令底下找到一些範例程式。

儲存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)狀態,避免讀寫器重複讀取同一張卡片:

讀取Mifare卡片與衝突處理流程

SAK代表select acknowledge,直譯為「選擇應答」,是由卡片發給讀寫器,對於選擇卡片命令的回應,不同類型的Mifare卡片的SAK值不一樣(例如,Mifare Classic的SAK值為0x18),程式可藉此判別感應到的卡片類型。詳細的防衝突處理與SAK值判斷流程,請參閱NXP公司的“MIFARE ISO/IEC 14443 PICC Selection”技術文件(PDF格式)。

讀取Mifare卡片類型及其UID碼的程式如下:

程式第20行宣告一個指向儲存UID值的指標變數(假設UID碼的長度為4):

指向儲存UID值的指標變數

第25行的“MFRC522::PICC_Type”代表引用在MFRC522類別(程式庫)裡面定義的PICC_Type這個資料類型,其中的雙冒號(::)代表範圍解析運算子(scope-resolution operator),用來表示“PICC_Type”定義在MFRC522程式庫裡面。如果不用雙冒號指出“PICC_Type”資料類型的來源,程式編譯器會產生未定義之類的錯誤。

上傳程式碼之後,開啟序列埠監控視窗,你可以嘗試一次讓Mifare模組感應多個卡片(筆者同時用3個),它將能逐一顯示每個卡片的類型和UID:

序列埠監控視窗

除非這些卡片離開、再次進入感應區,否則它們不會被重複讀取。

延伸閱讀

35 thoughts on “Mifare RFID-RC522模組實驗(一):讀取Mifare RFID卡的UID識別碼

    1. hi scott:

      沒有錯喔~第一段指的是書本範例所採用的RFID模組(非Mifare),載波頻率是125KHz;本文採用的Mifare是13.56MHz。

      thanks,
      jeffrey

    2. 因為你第二段講的是HF,我以為你第一段打的頻率LF是打錯的,SORRY
      原來第一段是補充書的內容
      MIFARE是另外提出的
      看太快了,抱歉

  1. 趙老師我想請問一下~
    Mifare RFID-RC522線路圖接好了,程式庫也下載了
    程式驗證,上傳沒有題,
    序列視窗有出現
    RFID reader is ready
    可是卡片靠上去,序列視窗也都沒有反應!!!
    在想說是不是買到地雷模組了…

    老師你的模組都是在網路上買,還是在實體店面買的呢?

    1. hi johnny:

      有可能…假若你曾把它的電源誤接到5V,那它八成是故障了。
      模組大多是在網路上購買的。

      thanks,
      jeffrey

  2. 趙老師 請問一下 RFID-RC522這個模組到底該接3.3V,還是5V? 有些網站建議使用5V 那一陣子用了好像也沒問題
    最近要再使用的時候發現完全都無法讀卡片,我該怎麼確認RC522模組是正常的?再買一組來測試嗎?

  3. 你好
    請問可以借用網頁的第二張圖片來使用嗎?(MFRC522晶片那張)
    因為圖片畫得很精美
    想放進課程期末報告裡面使用

    謝謝~ :)

  4. 老師,請問一下
    為什麼我程式碼在驗證就出錯了
    MFRC522的程式庫我有丟進去了也更新到最新了
    目前發現兩個問題是
    1.’id’ was not declared in this scope
    byte *id = mfrc522.uid.uidByte; 的宣告好像就出問題了這邊有需要注意的嗎

    2.’class MFRC522′ has no member named ‘PICC_HaLtA’
    這邊的讓程式停止的程序不在他的城市庫裏面的意思嗎

    1. 如果連程式庫的範例都無法順利編譯,那應該是你選用了程式庫不支援的控制板。

      thanks,
      jeffrey

  5. 老師你好
    前面的問題我解決好了
    現在是能順利執行的
    但是我發現如果卡片uid有”0″的話
    會顯示空白

  6. 趙老師請問一下~
    Mifare RFID-RC522線路圖接好了,程式庫也下載了
    程式驗證,上傳沒有題,
    序列視窗有出現
    RFID reader is ready
    可是卡片靠上去,序列視窗也都沒有反應!!!

  7. 老師請問一下~
    我照著您書上寫的,可是卡片靠上去,都沒有反應!!!真是@#$#*%
    是因為新卡還沒資料所以沒反應嗎???

  8. 趙老師請問一下~

    顯示出來的識別碼要如何存取?
    我要在感應到正確卡片時點亮LED燈,但是我使用了其他不同的晶片它也會點亮

    我只接讀取HEX的值,不知道是不是我的判斷是錯誤,以下是我判斷的程式。
    謝謝指教。
    if (*id = HEX)
    {
    digitalWrite(led, HIGH);
    }
    else
    {
    digitalWrite(led, LOW);
    }

    1. Mifare RFID-RC522讀寫器模組採用SPI介面,所以理論上你可以同時連接多組,只要每個模組的SDA分別接到Arduino的不同接腳即可。可是,硬體上可行,軟體操作上應該會遇到資料衝突的問題,因為程式每一次只能選取一個SPI裝置,若在讀取A裝置資料的同時,B裝置有資料進來,就會漏接。

      所以,不要想太多,一個Arduino板只接一個Mifare RFID-RC522讀寫器模組,然後你把這些Arduino板當成I2C slave,其中一個當作I2C master,串接起來,這樣應該可以解決你的問題。

      thanks,
      jeffrey

  9. 老師,你好

    多謝你無私分享
    已試過讀取白卡是OK的!!
    想問一下家中想做個門禁系統的話
    可以讀取悠遊卡,(香港八達通)數據嗎?
    (或者直接問,ARDUINO可以讀取悠遊卡數據嗎?)
    謝謝

    1. 非常感謝!我試過感應具備悠遊卡的信用卡,可以讀取到UID,卡片類型顯示Unknown type(未知類型)。寫入資料的話,沒試過,應該不行,因為不知道它的區段密碼。

      thanks,
      jeffrey

  10. 您好 實測是成功的 不知道能否轉仔您的圖片到自己的部落格 會保留浮水印跟標明圖片來源

    另外想問一下整塊晶片的腳位是除了A0和D10外都是綁死的嗎?

    謝謝您

  11. 請問 有沒有單純用SPI寫RC522的範例

    看arduino的Library不是很明白

    想要用其他單晶片寫SPI跟他溝通

    但網路上的教學看不太懂

  12. 有試著讀過

    可以讀取他的暫存器

    但是看不太懂 要如何去讀取RFID 的 UID

    我也試著看Arduino RC522的Library 去照著他去一點一點地改寫

    但還是無法讀取到UID 只能讀寫暫存器

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *