2025年11月7日 星期五

Polling for Cards (卡片詢問) 步驟

Polling for Cards (卡片詢問) 步驟

根據您提供的 PDF 文件 (AN10834 - MIFARE ISO/IEC 14443 PICC Selection) 和圖片,我將專注於說明卡片啟動的第一個關鍵步驟:Polling for cards (卡片詢問)

這一流程主要涉及讀卡器 (PCD) 發送詢問命令,以及卡片 (PICC) 回覆一個狀態字節,以表示它的存在和類型。


第一部分:Polling for Cards (卡片詢問) 步驟說明

根據您提供的 PDF 文件中的 2.1 Polling for cards 內容,這個步驟用於確認射頻場 (RF field) 內是否存在符合 ISO/IEC 14443 Type A 或 Type B 標準的卡片。

流程概述:

步驟編號動作主體傳輸內容 (命令)傳輸內容 (響應)目的
1.PCD (讀卡器)RF Field ONN/A啟動射頻場,並等待 5ms (T(min)_rf_on)。
2.PCD (讀卡器)REQA (REQuest type A)N/APCD 發送 Type A 詢問命令 (7位元長度)。
3.PICC (卡片)N/AATQA (Answer To reQuest type A)MIFARE 1K 卡片 回覆 ATQA (2 個位元組),表示它的存在和基本類型。
4.PCD (讀卡器)N/A(接收 ATQA)PCD 接收到 ATQA 後,確認 Type A 卡片在場,然後進入下一步:Activate Card (卡片啟動,即防衝突流程)。

MIFARE 1K 卡的關鍵數據:

  • REQA (Type A 詢問命令): 通常是 26 (十六進制)。

  • ATQA (Type A 響應): 對於 MIFARE Classic 1K,ATQA 的值通常是 00 04 或類似於 xx 04 的結構(其中 04 表示其屬於 NXP MIFARE Classic 家族,並使用 7-byte UID)。


第二部分:Python Tkinter 模擬 Polling 流程

以下是使用 Python tkinter 建立一個簡單 GUI 來視覺化上述 Polling for Cards 步驟的程式碼架構。它將專注於 REQA 命令發送與 ATQA 響應接收的過程。









import tkinter as tk

from tkinter import ttk


class PollingSimulator:

    def __init__(self, master):

        self.master = master

        master.title("MIFARE 卡片詢問 (Polling for Cards) 模擬")


        # 模擬數據

        self.REQA_COMMAND = "26 (Hex)"

        self.MIFARE_1K_ATQA = "00 04 (Hex)"

        

        # 狀態變數

        self.step_text = tk.StringVar()

        self.status_text = tk.StringVar()

        self.current_step = 0

        self.max_step = 4


        # 初始化介面

        self.create_widgets()

        self.reset_flow()


    def create_widgets(self):

        # 標題

        ttk.Label(self.master, text="ISO/IEC 14443-A Polling 流程", font=('Arial', 14, 'bold')).grid(row=0, column=0, columnspan=2, pady=10)

        

        # 步驟顯示

        ttk.Label(self.master, text="當前步驟:", font=('Arial', 10, 'bold')).grid(row=1, column=0, sticky='w', padx=10, pady=5)

        self.step_label = ttk.Label(self.master, textvariable=self.step_text, font=('Arial', 10, 'italic'), foreground='blue')

        self.step_label.grid(row=1, column=1, sticky='w', pady=5)


        # 狀態與結果顯示

        ttk.Label(self.master, text="流程狀態:", font=('Arial', 10, 'bold')).grid(row=2, column=0, sticky='w', padx=10, pady=5)

        self.status_label = ttk.Label(self.master, textvariable=self.status_text, wraplength=400, justify=tk.LEFT, font=('Arial', 10))

        self.status_label.grid(row=2, column=1, sticky='w', pady=5)

        

        # 關鍵數據區

        data_frame = ttk.LabelFrame(self.master, text="傳輸數據")

        data_frame.grid(row=3, column=0, columnspan=2, padx=10, pady=10, sticky="ew")

        

        ttk.Label(data_frame, text="REQA 命令:").grid(row=0, column=0, padx=5, pady=2, sticky='w')

        ttk.Label(data_frame, text=self.REQA_COMMAND, foreground='darkred').grid(row=0, column=1, padx=5, pady=2, sticky='w')


        ttk.Label(data_frame, text="MIFARE 1K ATQA:").grid(row=1, column=0, padx=5, pady=2, sticky='w')

        ttk.Label(data_frame, text=self.MIFARE_1K_ATQA, foreground='darkgreen').grid(row=1, column=1, padx=5, pady=2, sticky='w')


        # 操作按鈕

        self.next_button = ttk.Button(self.master, text="執行下一動作", command=self.next_step)

        self.next_button.grid(row=4, column=0, pady=10, padx=10, sticky='e')

        

        self.reset_button = ttk.Button(self.master, text="重置流程", command=self.reset_flow)

        self.reset_button.grid(row=4, column=1, pady=10, padx=10, sticky='w')


    def reset_flow(self):

        self.current_step = 0

        self.step_text.set(f"0/{self.max_step}")

        self.status_text.set("準備就緒。PCD 尚未啟動 RF 載波。")

        self.next_button.config(state=tk.NORMAL)


    def next_step(self):

        self.current_step += 1

        self.step_text.set(f"{self.current_step}/{self.max_step}")

        

        if self.current_step == 1:

            # 步驟 1: 啟動 RF

            self.status_text.set(

                f"[動作 1] PCD 動作:啟動 RF 載波 (RF Field ON)。\n"

                f"PCD 等待 T(min)_rf_on (至少 5ms) 以確保 PICC 準備就緒。"

            )

            self.next_button.config(text="發送 REQA 命令")


        elif self.current_step == 2:

            # 步驟 2: PCD 發送 REQA

            self.status_text.set(

                f"[動作 2] PCD 動作:發送 Type A 詢問命令 (REQA)。\n"

                f"PCD 廣播 REQA ({self.REQA_COMMAND}),詢問 Type A 卡片是否存在。"

            )

            self.next_button.config(text="等待 PICC 響應 ATQA")


        elif self.current_step == 3:

            # 步驟 3: PICC 回覆 ATQA

            self.status_text.set(

                f"[動作 3] PICC 動作:MIFARE 1K 卡片回覆 ATQA。\n"

                f"卡片響應 ATQA ({self.MIFARE_1K_ATQA}),確認其存在和基本類型。"

            )

            self.next_button.config(text="PCD 確認卡片在場")


        elif self.current_step == 4:

            # 步驟 4: 流程結束並進入下一階段

            self.status_text.set(

                f"[動作 4] PCD 動作:接收並解析 ATQA,確認是 Type A 卡。\n"

                f"Polling 步驟完成。PCD 準備進入 **卡片啟動/防衝突 (Activate Card/Anti-collision)** 流程。"

            )

            self.next_button.config(state=tk.DISABLED, text="Polling 流程結束")


        else:

            self.status_text.set("流程結束。請點擊 '重置流程' 重新開始。")

            self.next_button.config(state=tk.DISABLED)


if __name__ == "__main__":

    root = tk.Tk()

    app = PollingSimulator(root)

    root.geometry("500x350")

    root.mainloop()

程式碼執行說明:

  1. 環境需求: 確保您的 Python 環境安裝了 tkinter 庫。

  2. 執行效果: 運行上述程式碼後,會彈出一個 GUI 視窗,模擬 Polling 流程。

  3. 操作流程:

    • 點擊「執行下一動作」按鈕。

    • 視窗將依序顯示 PCD 啟動 RF、發送 REQA 命令、MIFARE 1K 卡片回覆 ATQA,直到最終 PCD 確認卡片在場,準備進入防衝突階段。

    • 這視覺化了從射頻啟動到確認卡片存在的整個 Polling 過程。

沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...