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

如何使用Arduino向RFID标签跨块写入长字符串

Arduino + MFRC522 向MIFARE标签写入长字符串实现

前置注意事项

操作MIFARE系列RFID标签必须避开两类特殊块,否则会直接导致标签永久锁死报废:

  • 块0:厂商固化只读块,存储标签UID等出厂信息,不可写入
  • 扇区尾块:每个扇区共4个块,索引为3、7、11、15…(块号对4取余等于3)的块为扇区控制块,存储读写密钥和权限配置,不可写入用户数据

实现思路

受标签硬件限制,单个数据块最多写入16字节,长字符串写入逻辑如下:

  • 从指定的安全起始块(推荐从块1开始)写入
  • 把长字符串按每16字节拆分一组,不足16字节的末尾用0填充补满
  • 逐块写入时自动跳过扇区尾块,直到所有字符串内容写完
  • 读取时按写入的块顺序逐块读取,拼接后去掉末尾填充的0即可得到原始字符串

完整可运行代码

#include <SPI.h>
#include <MFRC522.h>

// 硬件引脚定义
#define SS_PIN 10
#define RST_PIN 7

MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;

const byte START_BLOCK = 1; // 写入起始块,避开块0厂商块
const char* writeStr = "Hello my name is james and i live in NewYork"; // 待写入长字符串
byte bufferLen = 18; // 单块读取缓冲长度固定为18字节(16字节数据+2字节校验)
MFRC522::StatusCode status;

void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();
  Serial.println("请放置MIFARE标签到读卡区...");
  // 初始化默认密钥,出厂标签密钥A默认全FF
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

void loop() {
  // 检测新卡
  if (!mfrc522.PICC_IsNewCardPresent()) return;
  if (!mfrc522.PICC_ReadCardSerial()) return;

  Serial.println(F("检测到标签,开始写入长字符串..."));
  // 写入长字符串
  writeLongString(START_BLOCK, writeStr);
  // 读取长字符串
  String readStr = readLongString(START_BLOCK, strlen(writeStr));
  Serial.print("读取到的完整字符串:");
  Serial.println(readStr);

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  Serial.println("操作完成,可以移走标签");
}

// 单块写入函数
bool writeSingleBlock(byte blockNum, byte* data) {
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockNum, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("块");Serial.print(blockNum);Serial.print("认证失败:");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
  status = mfrc522.MIFARE_Write(blockNum, data, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("块");Serial.print(blockNum);Serial.print("写入失败:");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
  Serial.print("块");Serial.print(blockNum);Serial.println("写入成功");
  return true;
}

// 长字符串写入函数
void writeLongString(byte startBlock, const char* str) {
  byte currentBlock = startBlock;
  int strLen = strlen(str);
  int offset = 0;
  byte blockBuf[16];

  while (offset < strLen) {
    // 跳过扇区尾块
    if (currentBlock %4 ==3) {
      currentBlock++;
      continue;
    }
    // 清空块缓冲
    memset(blockBuf, 0, 16);
    // 拷贝最多16字节数据到缓冲
    int copyLen = min(16, strLen - offset);
    memcpy(blockBuf, str+offset, copyLen);
    // 写入块
    writeSingleBlock(currentBlock, blockBuf);
    offset += copyLen;
    currentBlock++;
  }
}

// 单块读取函数
bool readSingleBlock(byte blockNum, byte* outBuf) {
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockNum, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("块");Serial.print(blockNum);Serial.print("认证失败:");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
  byte readBuf[18];
  byte bufSize = 18;
  status = mfrc522.MIFARE_Read(blockNum, readBuf, &bufSize);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("块");Serial.print(blockNum);Serial.print("读取失败:");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
  // 拷贝16字节有效数据
  memcpy(outBuf, readBuf, 16);
  return true;
}

// 长字符串读取函数
String readLongString(byte startBlock, int totalLen) {
  String result = "";
  byte currentBlock = startBlock;
  int readOffset =0;
  byte blockBuf[16];

  while (readOffset < totalLen) {
    // 跳过扇区尾块
    if (currentBlock%4 ==3) {
      currentBlock++;
      continue;
    }
    if (readSingleBlock(currentBlock, blockBuf)) {
      int copyLen = min(16, totalLen - readOffset);
      for (int i=0; i<copyLen; i++) {
        result += (char)blockBuf[i];
      }
      readOffset += copyLen;
    } else {
      break;
    }
    currentBlock++;
  }
  return result;
}

代码说明

  • 写入前自动初始化标签默认出厂密钥FFFFFFFFFFFF,如果你的标签修改过密钥,需要替换key.keyByte数组里的值
  • 单块写入、读取的核心逻辑和原有单块操作代码一致,新增了长字符串拆分、块地址校验、自动跳过特殊块的逻辑
  • MIFARE 1K标签最多可存储768字节用户文本,足够存储短个人信息、网址类内容
  • 如果需要写入更长内容,可以更换MIFARE 4K标签,逻辑无需修改,只要保持扇区尾块跳过规则一致即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:12:09