arduino r3 使用rc522读写cuid卡片

11/6/2022 11:09:11 PM
956
0

3.3V供电、GND接地不用多说,IRQ是中断才用到的此处没有用到可以不接,其余5个引脚接法如下表所示:

 /* Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 */

代码

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

#define RST_PIN 9  // Configurable, see typical pin layout above
#define SS_PIN 10  // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
MFRC522::MIFARE_Key key;

void setup() {
  Serial.begin(9600);  // Initialize serial communications with the PC
  while (!Serial)      //端口打开失败什么都不做
    ;
  SPI.begin();         // Init SPI bus
  mfrc522.PCD_Init();  // Init MFRC522
  // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
  Serial.print(F("Using key (for A and B):"));
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
  Serial.println();
}

int state = 0;  //1=49  2=50 3=51
bool selectedcard = false;
// Init array that will store new NUID
byte nuidPICC[4];  //当前卡片的id
String cm1;

void loop() {

  if (state == 0 || state == 48) {
    //读取串口的数据
    if (Serial.available() > 0) {
      // read the incoming byte:
      state = Serial.read();
      //Serial.println(state);
    }
  } else {
    if (state != 49 && state != 50) {

      while (Serial.available() > 0) {
        cm1 += char(Serial.read());
        delay(2);
      }

      if (cm1.length() > 0) {
        Serial.print("输入");
        Serial.println(cm1);

        if (cm1.length() == 6 && cm1.compareTo("000000") == 0) {
          state = 0;
          return;
        }

        byte byteArray[cm1.length() / 2] = { 0 };
        hexCharacterStringToBytes(byteArray, cm1.c_str());
        printHex(byteArray, sizeof(byteArray));
        //Serial.println(tep_1);
        cm1 = "";
      }
    }
  }

  if (state == 49) {  //字符1
    Serial.println("开始读卡");
    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
    if (!mfrc522.PICC_IsNewCardPresent()) {
      Serial.println("没有检测到新卡片");
      state = 0;
      return;
    }

    // Select one of the cards
    if (!mfrc522.PICC_ReadCardSerial()) {
      Serial.println(("选卡失败"));
      state = 0;
      return;
    }

    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));
    if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType != MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
      Serial.println(F("卡片类型未知"));
    }

    //打印当前卡片id
    Serial.print(F("The NUID tag is:"));
    printHex(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println("");


    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
    state = 0;  //状态重置

  } else if (state == 50) {
    //接收数据,并写入卡片id
    Serial.println("等待输入新卡号");
    String temp2;
    while (Serial.available() > 0) {
      temp2 += char(Serial.read());
      delay(2);
    }

    byte inputID[4] = { 0 };
    byte paritybit;
    if (temp2.length() > 0) {
      if (temp2.length() != 8) {
        Serial.println("卡号id应是个8位数");
        state = 0;
        return;
      }

      hexCharacterStringToBytes(inputID, temp2.c_str());
      Serial.println("输入的卡号是:");
      printHex(inputID, sizeof(inputID));
      Serial.println("");
      paritybit = idChecksum(inputID);  //计算校验位
      Serial.print("id校验码:");
      Serial.println(paritybit, HEX);
    } else {
      return;
    }
    //读取缓冲区的内容,如果内容不存在,则 retrun;

    //准备读取新卡,并打印新卡的id
    if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
      Serial.println(F("卡片读取失败,请确认"));
      delay(50);
      state = 0;
      return;
    }

    Serial.print(F("当前卡片的 UID:"));
    printHex(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println("");
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType != MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
      Serial.println("不支持的卡片类型.");
      state = 0;
      return;
    }

    byte sector = 0;     //0扇区
    byte blockAddr = 0;  //第0块

    Serial.print(F("Reading data from block "));
    Serial.print(blockAddr);

    MFRC522::StatusCode status;
    byte buffer[18];
    byte size = sizeof(buffer);
    byte trailerBlock = 3;  //授权验证的块号
    // Authenticate using key A  使用密钥A进行授权
    Serial.println(F("Authenticating using key A..."));
    status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("PCD_Authenticate() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      state = 0;
      return;
    }

    status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("读取数据块失败: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      state = 0;
      return;  //读取卡片失败,退出
    }
    Serial.print(F("Data in block "));
    Serial.print(blockAddr);
    Serial.print(F(":"));
    printHex(buffer, 16);
    Serial.println();

    //写入前需要校验Key B
    Serial.println(F("Authenticating again using key B..."));
    status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("PCD_Authenticate() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      state = 0;
      return;
    }

    //设置0块的数据,以备写入
    buffer[0] = inputID[0];
    buffer[1] = inputID[1];
    buffer[2] = inputID[2];
    buffer[3] = inputID[3];
    buffer[4] = paritybit;

    //写入到当前卡的id中
    status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(blockAddr, buffer, 16);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Write() failed, 失败: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }
    Serial.println("写入完毕,当前卡片数据:");
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
    state = 0;  //状态重置
  }
}



//bcc校验,求uid的 校验位
byte idChecksum(byte *buffer) {
  return buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
}


/**
* Helper routine to dump a byte array as hex values to Serial. 
*/
void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? "0" : "");
    Serial.print(buffer[i], HEX);
    Serial.print(" ");
  }
}

void hexCharacterStringToBytes(byte *byteArray, const char *hexString) {
  bool oddLength = strlen(hexString) & 1;

  byte currentByte = 0;
  byte byteIndex = 0;

  for (byte charIndex = 0; charIndex < strlen(hexString); charIndex++) {
    bool oddCharIndex = charIndex & 1;

    if (oddLength) {
      // If the length is odd
      if (oddCharIndex) {
        // odd characters go in high nibble
        currentByte = nibble(hexString[charIndex]) << 4;
      } else {
        // Even characters go into low nibble
        currentByte |= nibble(hexString[charIndex]);
        byteArray[byteIndex++] = currentByte;
        currentByte = 0;
      }
    } else {
      // If the length is even
      if (!oddCharIndex) {
        // Odd characters go into the high nibble
        currentByte = nibble(hexString[charIndex]) << 4;
      } else {
        // Odd characters go into low nibble
        currentByte |= nibble(hexString[charIndex]);
        byteArray[byteIndex++] = currentByte;
        currentByte = 0;
      }
    }
  }
}

byte nibble(char c) {
  if (c >= '0' && c <= '9')
    return c - '0';

  if (c >= 'a' && c <= 'f')
    return c - 'a' + 10;

  if (c >= 'A' && c <= 'F')
    return c - 'A' + 10;

  return 0;  // Not a valid hexadecimal character
}

使用说明

1、代码中注释 1=49 2=50 3=51  这里指的是 1、2、3对应的Ascii码,串口读取的是字符串对应的ASCII码

2、输入<1>读取卡片,输入<2>将读取的卡片值写入到新的卡片中,<000000>重置状态初始化程序 ,<3>未使用

输出:

实验中主要输出卡片数据的是语句:

mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

使用默认的 FF FF FF FF FF FF作为密码读取卡片数据。

 

执行:在串口中输入  01(byte类型) 或者 1(string) 响应。

Scan a MIFARE Classic PICC to demonstrate read and write.
Using key (for A and B):FF FF FF FF FF FF 
开始读卡
PICC type: MIFARE 1KB
The NUID tag is:2E 1C F5 FF
Card UID: 2E 1C F5 FF
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         62   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         61   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         60   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
  14     59   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         58   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         57   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         56   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
  13     55   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         54   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         53   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         52   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
  12     51   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         50   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         49   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         48   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
  11     47   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         46   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         45   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         44   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
  10     43   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         42   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         41   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         40   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   9     39   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         38   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         37   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         36   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   8     35   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         34   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         33   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         32   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   7     31   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         30   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         29   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         28   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   6     27   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         26   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         25   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         24   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   5     23   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         22   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         21   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         20   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   4     19   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         18   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         17   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         16   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   3     15   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         14   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         13   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
         12   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   2     11   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
         10   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          9   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          8   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
          6   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          5   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          4   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
   0      3   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 
          2   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          1   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ] 
          0   2E 1B F2 7D  BA 08 04 00  62 63 64 65  66 67 68 69  [ 0 0 0 ] 

自定义密码卡片的输出如下

开始读卡
PICC type: MIFARE 1KB
The NUID tag is:3E F5 E9 7D 
Card UID: 3E F5 E9 7D
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
  15     63  PCD_Authenticate() failed: Error in communication.
  14     59  PCD_Authenticate() failed: Timeout in communication.
  13     55  PCD_Authenticate() failed: Timeout in communication.
  12     51  PCD_Authenticate() failed: Timeout in communication.
  11     47  PCD_Authenticate() failed: Timeout in communication.
  10     43  PCD_Authenticate() failed: Timeout in communication.
   9     39  PCD_Authenticate() failed: Timeout in communication.
   8     35  PCD_Authenticate() failed: Timeout in communication.
   7     31  PCD_Authenticate() failed: Timeout in communication.
   6     27  PCD_Authenticate() failed: Timeout in communication.
   5     23  PCD_Authenticate() failed: Timeout in communication.
   4     19  PCD_Authenticate() failed: Timeout in communication.
   3     15  PCD_Authenticate() failed: Timeout in communication.
   2     11  PCD_Authenticate() failed: Timeout in communication.
   1      7  PCD_Authenticate() failed: Timeout in communication.
   0      3  PCD_Authenticate() failed: Timeout in communication.

 

全部评论



提问