You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RFID 522卡上永久存储余额?ESP32复位后余额保留方案

解决方案:将余额永久存储在RFID卡的扇区中

核心逻辑

MIFARE Classic系列卡(如1K/4K)包含可自定义读写的用户扇区,我们需要把余额数据写入卡的指定扇区块中,而非仅存在ESP32的RAM里。每次刷卡时先读取卡上存储的余额,累加后再写回卡内,这样ESP32复位后,再次刷卡仍能读取到之前的累计余额。

具体实现步骤

1. 选定存储区域

以MIFARE Classic 1K卡为例,选择**扇区1的块1(地址0x05)**存储余额(扇区0的块0是厂商信息块,不可写入)。默认情况下,多数卡的扇区密钥为FFFFFFFFFFFF,可直接用此密钥验证读写权限。

2. 编写余额读写函数

读取余额函数

// 从指定块读取余额,返回余额数值(单位:美元),读取失败返回-1
int readBalance(byte blockAddr, byte* authKey) {
  int balance = 0;
  byte dataBuffer[18];
  byte dataSize = sizeof(dataBuffer);

  // 验证扇区密钥(扇区1的密钥块地址是0x07)
  if (!mfrc522.PCD_Authenticate(PICC_CMD_MF_AUTH_KEY_A, 0x07, authKey, &mfrc522.uid)) {
    Serial.println("密钥验证失败");
    mfrc522.PCD_StopCrypto1();
    return -1;
  }

  // 读取目标块数据
  if (mfrc522.MIFARE_Read(blockAddr, dataBuffer, &dataSize)) {
    // 将4字节数据拼接为整数(大端模式)
    balance = (dataBuffer[0] << 24) | (dataBuffer[1] << 16) | (dataBuffer[2] << 8) | dataBuffer[3];
  } else {
    Serial.println("余额读取失败");
    balance = -1;
  }

  mfrc522.PCD_StopCrypto1();
  return balance;
}

写入余额函数

// 将余额写入指定块,写入成功返回true,失败返回false
bool writeBalance(byte blockAddr, byte* authKey, int balance) {
  byte dataBuffer[16]; // MIFARE单块固定为16字节
  memset(dataBuffer, 0, 16); // 初始化缓冲区

  // 将整数余额拆分为4字节(大端模式)
  dataBuffer[0] = (balance >> 24) & 0xFF;
  dataBuffer[1] = (balance >> 16) & 0xFF;
  dataBuffer[2] = (balance >> 8) & 0xFF;
  dataBuffer[3] = balance & 0xFF;

  // 验证扇区密钥
  if (!mfrc522.PCD_Authenticate(PICC_CMD_MF_AUTH_KEY_A, 0x07, authKey, &mfrc522.uid)) {
    Serial.println("密钥验证失败");
    mfrc522.PCD_StopCrypto1();
    return false;
  }

  // 写入数据到目标块
  bool writeSuccess = mfrc522.MIFARE_Write(blockAddr, dataBuffer, 16);
  if (!writeSuccess) {
    Serial.println("余额写入失败");
  }

  mfrc522.PCD_StopCrypto1();
  return writeSuccess;
}

3. 修改主刷卡逻辑

替换原有仅在RAM中累加余额的代码,改为读写卡内数据:

byte defaultAuthKey[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 默认卡密钥
int currentBalance;

void loop() {
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
    // 读取卡内存储的余额
    currentBalance = readBalance(0x05, defaultAuthKey);

    // 若为新卡或读取失败,初始化余额为100美元
    if (currentBalance == -1) {
      currentBalance = 100;
      writeBalance(0x05, defaultAuthKey, currentBalance);
      Serial.print("新卡初始化余额:");
      Serial.println(currentBalance);
    } else {
      // 累加100美元后写回卡内
      currentBalance += 100;
      if (writeBalance(0x05, defaultAuthKey, currentBalance)) {
        Serial.print("余额更新为:");
        Serial.println(currentBalance);
      }
    }

    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
  }
}

4. 关键注意事项

  • 密钥匹配:如果卡的扇区密钥不是默认值,需先用RFID工具读取或修改对应扇区的密钥,确保验证时使用正确密钥。
  • 数据稳定性:示例用整数存储余额,若需精确到分,可将单位改为分(如100美元存为10000),避免浮点运算误差。
  • 扇区权限:确保所选扇区的访问控制位允许读写,部分卡的扇区默认是只读,需用工具调整访问控制配置。

内容的提问来源于stack exchange,提问作者Benjamin Veras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:10:18