WOKWI程式
// 定義 MFRC522 RFID read 與 ESP32 介面 接腳連接 Pin assign
/* Wiring RFID RC522 module
==============================================================
GND = GND 3.3V = 3.3V
The following table shows the typical pin layout used:
* MFRC522 ESP32
* Reader/PCD
* Signal Pin Pin
* -----------------------------------
* RST/Reset RST GPIO21
* SPI SS SDA(SS) GPIO5
* SPI MOSI MOSI GPIO23
* SPI MISO MISO GPIO19
* SPI SCK SCK GPIO18
=============================================================
* I2C LCD 16x2 接線:
* SDA --> GPIO 17
* SCL --> GPIO 16
=============================================================
*/
// Wifi 與 MQttClient 程式庫
#include <WiFi.h>
#include <ArduinoMqttClient.h>
// MFRC522 程式庫
#include <SPI.h>
#include <MFRC522.h>
// I2C 與 LCD 程式庫
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LED 13 // 定義 LED 接腳
// 定義 I2C LCD 腳位與實例 (Wokwi 模擬的 I2C 位址通常為 0x27)
#define I2C_SDA 17
#define I2C_SCL 16
LiquidCrystal_I2C lcd(0x27, 16, 2);
// === Wokwi 專屬的 Wi-Fi 設定 ===
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
// === MQTT Broker 設定 ===
const char broker[] = "broker.emqx.io";
int port = 1883;
String json = "";
// MQTT 主題定義
const char *SubTopic1 = "alex9ufo/2026/RFID/LED";
const char *PubTopic2 = "alex9ufo/2026/RFID/Back_LED";
const char *PubTopic3 = "alex9ufo/2026/RFID/RFID_UID";
const char *PubTopic4 = "alex9ufo/2026/RFID/RFID_PICC";
const char willTopic[] = "alex9ufo/2026/RFID/Starting";
//======================================================
#define RST_PIN 21
#define SS_PIN 5
MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
MFRC522::StatusCode status;
//===========================================================
bool Send = false;
String LEDjson = "OFF"; // 預設狀態為 OFF
// --- 非阻塞計時器變數 ---
unsigned long lcdResetTimer = 0;
bool lcdShowingCard = false;
const unsigned long displayDuration = 2000; // 卡片資訊在 LCD 顯示的時間 (2秒)
//===========================================================
// MQTT 訂閱訊息接收回呼函式 (當遠端發送指令給 ESP32 時觸發)
void onMqttMessage(int messageSize) {
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
String Topic = mqttClient.messageTopic();
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
String message = "";
while (mqttClient.available()) {
message += (char)mqttClient.read();
}
Serial.println(message);
message.trim();
Topic.trim();
if (Topic == "alex9ufo/2026/RFID/LED") {
if (message == "on") {
digitalWrite(LED, LOW); // 點亮 LED (低電位觸發)
LEDjson = "ON";
Send = true;
}
if (message == "off") {
digitalWrite(LED, HIGH); // 熄滅 LED
LEDjson = "OFF";
Send = true;
}
// 如果目前 LCD 不是在顯示剛刷卡的資訊,就即時更新 LCD 第二行
if (!lcdShowingCard) {
lcd.setCursor(0, 1);
lcd.print("LED: " + LEDjson + " ");
}
Serial.print("LED = ");
Serial.println(LEDjson);
Serial.println("\n-----------------------");
}
}
//===========================================================
// 16進位 Byte 陣列轉字串工具
String printHex(byte *buffer, byte bufferSize) {
String id = "";
for (byte i = 0; i < bufferSize; i++) {
id += buffer[i] < 0x10 ? "0" : "";
id += String(buffer[i], HEX);
id += " ";
}
return id;
}
//===========================================================
// Wi-Fi 連線程序
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
int dotCount = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.setCursor(dotCount % 16, 1);
lcd.print(".");
dotCount++;
}
Serial.println("\nWiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected!");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP().toString());
delay(1500);
}
//===========================================================
// MQTT 發行:回報當前 LED 狀態
void LED_Message() {
if (Send) {
Serial.print("Publish message: ");
Serial.println(LEDjson);
LEDjson.trim();
int qos = 0; // 改為 QoS 0 提高在公開 Broker 上的傳輸穩定度
bool retained = false;
bool dup = false;
mqttClient.beginMessage(PubTopic2, LEDjson.length(), retained, qos, dup);
mqttClient.print(LEDjson);
mqttClient.endMessage();
Send = false;
}
}
//===========================================================
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH); // 初始關閉 LED
Serial.begin(115200);
while (!Serial);
// 初始化自訂的 I2C 接腳 (SDA=17, SCL=16)
Wire.begin(I2C_SDA, I2C_SCL);
// 初始化 LCD
lcd.init();
lcd.backlight();
lcd.print("System Init...");
setup_wifi();
// 設定遺言訊息 (Last Will)
String willPayload = "ESP32 Disconnected";
bool willRetain = false;
int willQos = 0;
mqttClient.beginWill(willTopic, willPayload.length(), willRetain, willQos);
mqttClient.print(willPayload);
mqttClient.endWill();
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
lcd.clear();
lcd.print("Connect MQTT...");
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
lcd.clear();
lcd.print("MQTT Conn Fail!");
while (1);
}
Serial.println("You're connected to the MQTT broker!\n");
// 註冊訂閱接收市場與訂閱主題
mqttClient.onMessage(onMqttMessage);
int subscribeQos = 0;
mqttClient.subscribe(SubTopic1, subscribeQos);
// 初始化 RFID 模組
SPI.begin();
rfid.PCD_Init();
delay(4);
Serial.println("Scan PICC to see UID...");
// 進入主迴圈前的初始畫面
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scan RFID Card..");
lcd.setCursor(0, 1);
lcd.print("LED: OFF");
}
//===========================================================
void loop() {
// 保持 MQTT 心跳與背景訊息接收(非阻塞核心)
mqttClient.poll();
// 處理 LED 狀態發行回報
LED_Message();
// --- LCD 畫面自動復原計時檢查 ---
if (lcdShowingCard && (millis() - lcdResetTimer >= displayDuration)) {
lcdShowingCard = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scan RFID Card..");
lcd.setCursor(0, 1);
lcd.print("LED: " + LEDjson + " ");
}
// 檢查是否有新卡片被擺放,以及是否成功讀取
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
byte *id = rfid.uid.uidByte;
byte idSize = rfid.uid.size;
String Type;
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
Type = rfid.PICC_GetTypeName(piccType);
// 格式化 UID 字串
json = printHex(rfid.uid.uidByte, rfid.uid.size);
json.toUpperCase();
json.trim();
// ====== LCD 顯示邏輯更新 ======
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ID: " + json); // 第一行顯示 UID
lcd.setCursor(0, 1);
lcd.print("Type:" + Type.substring(0, 11)); // 第二行顯示卡片類型 (限制長度防止溢出)
// 啟動非阻塞計時器,標記目前正在展示卡片
lcdResetTimer = millis();
lcdShowingCard = true;
// =============================
// 發送 MQTT:卡片 UID 資訊
int qos = 0;
bool retained = false;
bool dup = false;
mqttClient.beginMessage(PubTopic3, json.length(), retained, qos, dup);
mqttClient.print(json);
mqttClient.endMessage();
// 發送 MQTT:卡片類型資訊
String typeJson = "PICC type: " + Type;
typeJson.trim();
mqttClient.beginMessage(PubTopic4, typeJson.length(), retained, qos, dup);
mqttClient.print(typeJson);
mqttClient.endMessage();
// 本機序列埠除錯輸出
Serial.println("Published UID: " + json);
Serial.println("Published Type: " + typeJson);
Serial.println();
// 讓卡片進入休眠,避免重複讀取
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
這份程式碼是經過優化後的完整版本,主要特點是結合了 MFRC522 RFID 讀卡、I2C LCD 16x2 顯示,以及基於 millis() 非阻塞計時器的 MQTT 雙向通訊。
以下為您進行這份優化版程式碼的逐行詳細說明:
1. 硬體連接與備忘註解
// 定義 MFRC522 RFID read 與 ESP32 介面 接腳連接 Pin assign
/* Wiring RFID RC522 module
==============================================================
GND = GND 3.3V = 3.3V
The following table shows the typical pin layout used:
* MFRC522 ESP32
* Reader/PCD
* Signal Pin Pin
* -----------------------------------
* RST/Reset RST GPIO21
* SPI SS SDA(SS) GPIO5
* SPI MOSI MOSI GPIO23
* SPI MISO MISO GPIO19
* SPI SCK SCK GPIO18
=============================================================
* I2C LCD 16x2 接線:
* SDA --> GPIO 17
* SCL --> GPIO 16
=============================================================
*/
說明:純文字註解,紀錄實體硬體或 Wokwi 模擬器上的接線定義。RFID 使用標準 VSPI 腳位(RST 改用 21);I2C LCD 則接在 GPIO 17 與 16。
2. 引入程式庫
// Wifi 與 MQttClient 程式庫
#include <WiFi.h>
#include <ArduinoMqttClient.h>
// MFRC522 程式庫
#include <SPI.h>
#include <MFRC522.h>
// I2C 與 LCD 程式庫
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>/<ArduinoMqttClient.h>:提供 Wi-Fi 連線與官方 MQTT 協定支援。#include <SPI.h>/<MFRC522.h>:驅動以 SPI 介面通訊的 RFID 讀卡機。#include <Wire.h>/<LiquidCrystal_I2C.h>:驅動 I2C 介面的液晶顯示器(LCD)。
3. 引腳、物件與 MQTT 主題定義
#define LED 13 // 定義 LED 接腳
// 定義 I2C LCD 腳位與實例 (Wokwi 模擬的 I2C 位址通常為 0x27)
#define I2C_SDA 17
#define I2C_SCL 16
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define LED 13:LED 連接到 GPIO 13。#define I2C_SDA 17/#define I2C_SCL 16:自訂 ESP32 的 I2C 腳位。LiquidCrystal_I2C lcd(0x27, 16, 2);:初始化 LCD 物件,設定 I2C 位址為0x27,規格為 16 欄 2 列。
// === Wokwi 專屬的 Wi-Fi 設定 ===
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
設定 Wokwi 線上模擬專用的模擬基地台 SSID 與無密碼設定。
建立底層 TCP 連線(
wifiClient)並將其包裝進 MQTT 客戶端(mqttClient)。
// === MQTT Broker 設定 ===
const char broker[] = "broker.emqx.io";
int port = 1883;
String json = "";
// MQTT 主題定義
const char *SubTopic1 = "alex9ufo/2026/RFID/LED";
const char *PubTopic2 = "alex9ufo/2026/RFID/Back_LED";
const char *PubTopic3 = "alex9ufo/2026/RFID/RFID_UID";
const char *PubTopic4 = "alex9ufo/2026/RFID/RFID_PICC";
const char willTopic[] = "alex9ufo/2026/RFID/Starting";
定義 EMQX 公開伺服器網址與預設的非加密通訊埠
1883。SubTopic1:訂閱接收控制 LED 指令的主題。PubTopic2 ~ 4與willTopic:發行狀態、UID、卡片類型與遺言的主題。
//======================================================
#define RST_PIN 21
#define SS_PIN 5
MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
MFRC522::StatusCode status;
建立 MFRC522 讀卡機實例,傳入晶片選擇引腳(5)與重置引腳(21)。
宣告金鑰(
key)與狀態變數(status)供後續呼叫。
4. 全域變數與非阻塞計時器宣告
bool Send = false;
String LEDjson = "OFF"; // 預設狀態為 OFF
// --- 非阻塞計時器變數 ---
unsigned long lcdResetTimer = 0;
bool lcdShowingCard = false;
const unsigned long displayDuration = 2000; // 卡片資訊在 LCD 顯示的時間 (2秒)
Send:觸發發行 LED 狀態的旗標。LEDjson:儲存當前 LED 狀態("ON" 或 "OFF")。lcdResetTimer:紀錄刷卡時的時間戳記(單位:毫秒)。lcdShowingCard:布林旗標,用來標記「目前 LCD 是否正停留在顯示 UID 畫面上」。displayDuration:設定刷卡資訊要在 LCD 上停留多久(2000 毫秒 = 2 秒)。
5. 功能函式與內部邏輯
A. MQTT 訂閱訊息回呼 (Callback) 函式
void onMqttMessage(int messageSize) {
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
String Topic = mqttClient.messageTopic();
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
當遠端有人發布訊息到 ESP32 訂閱的主題時,此函式會被自動觸發。在序列埠輸出收到的主題與訊息大小。
String message = "";
while (mqttClient.available()) {
message += (char)mqttClient.read();
}
Serial.println(message);
message.trim();
Topic.trim();
透過迴圈讀取快取中的字元,拼裝成
message字串,並使用.trim()清除字串前後的多餘空白或換行符號。
if (Topic == "alex9ufo/2026/RFID/LED") {
if (message == "on") {
digitalWrite(LED, LOW); // 點亮 LED (低電位觸發)
LEDjson = "ON";
Send = true;
}
if (message == "off") {
digitalWrite(LED, HIGH); // 熄滅 LED
LEDjson = "OFF";
Send = true;
}
比對主題。如果收到小寫的
"on",將 GPIO 13 輸出低電位點亮 LED(許多開發板為低電位觸發),變數改為"ON",並將Send設為 true 準備回報。反之收到"off"則關燈。
// 如果目前 LCD 不是在顯示剛刷卡的資訊,就即時更新 LCD 第二行
if (!lcdShowingCard) {
lcd.setCursor(0, 1);
lcd.print("LED: " + LEDjson + " ");
}
Serial.print("LED = ");
Serial.println(LEDjson);
Serial.println("\n-----------------------");
}
}
邏輯檢查:如果 LCD 此刻沒有在顯示剛刷完卡的 UID 資訊(避免畫面被蓋掉),就立刻在 LCD 第二行刷新顯示目前的 LED 狀態,後方留空格用以覆蓋舊字。
B. 16 進位字串轉換工具
String printHex(byte *buffer, byte bufferSize) {
String id = "";
for (byte i = 0; i < bufferSize; i++) {
id += buffer[i] < 0x10 ? "0" : "";
id += String(buffer[i], HEX);
id += " ";
}
return id;
}
將 RFID 晶片讀出的原始二進位 Byte 陣列,逐一轉換成大寫 16 進位英數字串(補零處理,如
0A B3 2C),方便顯示與閱讀。
C. Wi-Fi 連線程序
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
int dotCount = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.setCursor(dotCount % 16, 1);
lcd.print(".");
dotCount++;
}
開始連接無線網路,並同時在 LCD 第一行印出
"Connecting WiFi"。運用
while迴圈每 0.5 秒檢查連線狀態,連線上之前,會在 LCD 第二行像跑馬燈一樣橫向列印點記號.。
Serial.println("\nWiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected!");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP().toString());
delay(1500);
}
連線成功後,本機序列埠輸出成功訊息,並在 LCD 上短暫顯示獲取的局域網路 IP 位址 1.5 秒。
D. MQTT 狀態發行 (回報 LED 狀態)
void LED_Message() {
if (Send) {
Serial.print("Publish message: ");
Serial.println(LEDjson);
LEDjson.trim();
int qos = 0; // 改為 QoS 0 提高在公開 Broker 上的傳輸穩定度
bool retained = false;
bool dup = false;
mqttClient.beginMessage(PubTopic2, LEDjson.length(), retained, qos, dup);
mqttClient.print(LEDjson);
mqttClient.endMessage();
Send = false;
}
}
檢查
Send旗標。若成立,則將當前最新的 LED 狀態字串發布至PubTopic2(.../Back_LED)。關鍵優化:此處將服務品質改為
qos = 0,這對公開且高流量的broker.emqx.io伺服器而言,可以大幅提高訊息成功收發的順暢度、降低連線被剔除的機率。
6. 初始化設定 (setup)
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH); // 初始關閉 LED
Serial.begin(115200);
while (!Serial);
// 初始化自訂的 I2C 接腳 (SDA=17, SCL=16)
Wire.begin(I2C_SDA, I2C_SCL);
// 初始化 LCD
lcd.init();
lcd.backlight();
lcd.print("System Init...");
配置 LED 為輸出腳位並預設關燈。開啟 115200 鮑率的序列埠。
呼叫
Wire.begin(17, 16)強制指定 I2C 介面的 SDA 與 SCL 硬體映射引腳。初始化 LCD 並點亮其背光,顯示
"System Init..."。
setup_wifi();
// 設定遺言訊息 (Last Will)
String willPayload = "ESP32 Disconnected";
bool willRetain = false;
int willQos = 0;
mqttClient.beginWill(willTopic, willPayload.length(), willRetain, willQos);
mqttClient.print(willPayload);
mqttClient.endWill();
呼叫 Wi-Fi 連線。
配置 MQTT 「遺言(Last Will)」機制。若設備未來發生異常斷線,伺服器會替它向
willTopic發布"ESP32 Disconnected"訊息。
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
lcd.clear();
lcd.print("Connect MQTT...");
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
lcd.clear();
lcd.print("MQTT Conn Fail!");
while (1);
}
Serial.println("You're connected to the MQTT broker!\n");
在 LCD 提示下嘗試連線至 MQTT Broker。如果連線失敗,則在 LCD 上顯示錯誤並進入死迴圈停機;成功則繼續。
// 註冊訂閱接收市場與訂閱主題
mqttClient.onMessage(onMqttMessage);
int subscribeQos = 0;
mqttClient.subscribe(SubTopic1, subscribeQos);
// 初始化 RFID 模組
SPI.begin();
rfid.PCD_Init();
delay(4);
Serial.println("Scan PICC to see UID...");
// 進入主迴圈前的初始畫面
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scan RFID Card..");
lcd.setCursor(0, 1);
lcd.print("LED: OFF");
}
訂閱 LED 控制主題(QoS 改為 0)。
開啟 SPI 匯流排並驅動 MFRC522 晶片初始化。
清除 LCD 畫面,將其設為待命刷卡狀態(第一行
Scan RFID Card..,第二行LED: OFF)。
7. 主程式工作迴圈 (loop)
void loop() {
// 保持 MQTT 心跳與背景訊息接收(非阻塞核心)
mqttClient.poll();
// 處理 LED 狀態發行回報
LED_Message();
mqttClient.poll():每毫秒高頻維持與遠端 Broker 的長連線,並檢查有無最新訂閱訊息。隨時檢查有無 LED 狀態需要發行回報。
// --- LCD 畫面自動復原計時檢查 ---
if (lcdShowingCard && (millis() - lcdResetTimer >= displayDuration)) {
lcdShowingCard = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scan RFID Card..");
lcd.setCursor(0, 1);
lcd.print("LED: " + LEDjson + " ");
}
關鍵計時邏輯(非阻塞式):如果目前 LCD 正在顯示刷卡資訊(
lcdShowingCard == true),程式不會用delay()卡死,而是用現時時間(millis())減去刷卡當下的時間。一旦滿 2000 毫秒(2 秒),會自動把標記設回 false,並將 LCD 復原為預設待命畫面,同時顯示當下真實的 LED 狀態。這確保了在等待這 2 秒的期間,MQTT 指令依然進得來、LED 依然能被控制。
// 檢查是否有新卡片被擺放,以及是否成功讀取
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
byte *id = rfid.uid.uidByte;
byte idSize = rfid.uid.size;
String Type;
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
Type = rfid.PICC_GetTypeName(piccType);
// 格式化 UID 字串
json = printHex(rfid.uid.uidByte, rfid.uid.size);
json.toUpperCase();
json.trim();
偵測到有新卡片放入且成功讀取序列號。
辨識卡片 SAK 規格取得類型,並呼叫
printHex轉換出 UID 16 進位字串。
// ====== LCD 顯示邏輯更新 ======
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ID: " + json); // 第一行顯示 UID
lcd.setCursor(0, 1);
lcd.print("Type:" + Type.substring(0, 11)); // 第二行顯示卡片類型 (限制長度防止溢出)
// 啟動非阻塞計時器,標記目前正在展示卡片
lcdResetTimer = millis();
lcdShowingCard = true;
// =============================
清除 LCD 舊畫面。第一行印出
"ID: 8A 2F ..."。第二行印出
"Type:"加上截取前 11 個字元的類型名稱(防止字串過長溢出螢幕)。紀錄當前時間戳記到
lcdResetTimer,並將lcdShowingCard設為 true 啟動倒數。
// 發送 MQTT:卡片 UID 資訊
int qos = 0;
bool retained = false;
bool dup = false;
mqttClient.beginMessage(PubTopic3, json.length(), retained, qos, dup);
mqttClient.print(json);
mqttClient.endMessage();
// 發送 MQTT:卡片類型資訊
String typeJson = "PICC type: " + Type;
typeJson.trim();
mqttClient.beginMessage(PubTopic4, typeJson.length(), retained, qos, dup);
mqttClient.print(typeJson);
mqttClient.endMessage();
// 本機序列埠除錯輸出
Serial.println("Published UID: " + json);
Serial.println("Published Type: " + typeJson);
Serial.println();
// 讓卡片進入休眠,避免重複讀取
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
將讀取到的 UID 資訊與 PICC 類型字串分別發行至
PubTopic3與PubTopic4。序列埠輸出訊息以供監控除錯。
執行卡片休眠命令(
PICC_HaltA()與PCD_StopCrypto1()),釋放與該感應卡的加密連線,等待下一次新卡片切入。