实验六 RFID应用

实验六  RFID应用


一、实验目的

通过本实验,了解射频识别技术(RFID)的基本工作原理,掌握在Arduino项目中使用RFID读卡模块读取和写入标签信息的基本方法,熟悉RFID读卡模块仅读取指定标签内容的应用领域及设置方法。


二、实验要求

 1、使用ESP 8266电路板、RC522 RFID读卡器(如图14-1所示)、RFID标签(如图14-2所示)和导线搭建实验电路并编写相应Arduino程序代码,通过标签靠近读卡器读取标签信息,在串口监视器中观察读取到的内容。

6-1 RC522 RFID读卡器                   图6-2 RC522 RFID标签

 2、修改程序代码,实现RC522 RFID读卡器仅能读取指定RFID标签信息的功能。

 3、修改程序代码,实现RC522 RFID读卡器向RFID标签中写入新信息并在串口监视器中显示的功能。


三、实验过程

 1、搭建实验电路

使用导线分别连接面包板的电源总线正极和负极到电路板的3V3GND接口;将RFID读卡器放置在面包板上,注意所有针脚必须在不同的行上,其中标注了3.3VGND的针脚分别使用导线连接到面包板电源总线正极和负极上;标注了SDA的针脚使用导线连接到电路板D2GPIO4)接口,标注了SCK的针脚连接到D5GPIO14)接口,标注了MOSI的针脚连接到D7GPIO13)接口,标注了MISO的针脚连接到D6GPIO12)接口,标注了RST的针脚连接到D1GPIO5)接口,不要连接任何线到标注了IRQ的针脚上。电路连接如图所示。

6-3实验电路连接图

 2、编写代码,实现读取RFID标签信息的功能

1)在新建的Arduino程序窗口中输入如下代码:

//引入对应的库文件,需下载更新相应库文件

#include <SPI.h>

#include <MFRC522.h>

//定义针脚连接的GPIO接口号

#define RST_PIN 5          

#define SS_PIN 4         

//创建MFRC522实例

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {

  //初始化各实例,并在串口监视器显示初始内容

  ESP.wdtDisable();

  Serial.begin(115200);

  SPI.begin();

  mfrc522.PCD_Init();

  Serial.println("");

  Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks"));

}

void loop() {

  //寻找新的标签

  if ( ! mfrc522.PICC_IsNewCardPresent()) {

    return;

  }

  if ( ! mfrc522.PICC_ReadCardSerial()) {

    return;

  }

  //调用相应库函数读取标签信息

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

  delay(5000);

}

2)将USB线缆插入计算机,待程序上传成功后打开串口监视器,将RFID标签靠近读卡器,观察读取到的标签信息,正确的实验结果应包括UIDSAKPICC type及各区块所存储的内容(以十六进制数的形式存储),如图所示。

6-4串口监视器输出实验结果

 3、编写代码,实现读取指定RFID标签信息的功能

1)在新建的Arduino程序窗口中输入如下代码:

#include <SPI.h>

#include <MFRC522.h>

#define RST_PIN 5          

#define SS_PIN 4         

MFRC522 mfrc522(SS_PIN, RST_PIN);

String read_rfid;  //定义变量,用于存储要输出显示的字符串内容

//此处填写要读取的RFID标签的UID号(该信息可以从上一个实验结果中获取)

//注意去除中间的空格,所有的字母必须小写

String ok_rfid = "********";

void setup() {

  ESP.wdtDisable();

  Serial.begin(115200);

  SPI.begin();  

  mfrc522.PCD_Init();

  Serial.println("");

  Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks"));

}

void dump_byte_array(byte *buffer, byte bufferSize) {

  read_rfid="";

  for (byte i = 0; i < bufferSize; i++) {

     read_rfid=read_rfid + String(buffer[i], HEX);

  }

}

void loop() {

  if ( ! mfrc522.PICC_IsNewCardPresent()) {

    return;

  }

  if ( ! mfrc522.PICC_ReadCardSerial()) {

    return;

  }

  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);

  Serial.println(read_rfid);

  //判断读取到的标签UID号是否是指定标签的UID,若不是,则输出提示内容

  if (!(read_rfid == ok_rfid)) {

    Serial.println("Incorrect Tag");

    return;

  }

  //若读取的是指定的标签,则读取并显示标签内容

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

  delay(5000);

}

2)将USB线缆插入计算机,待程序上传成功后打开串口监视器,将RFID标签靠近读卡器,若欲读取标签的UID不是程序中设置的UID,则无法读取该标签信息,串口监视器中会出现如图14-5所示内容。

6-5读取失败时串口监视器输出的实验结果

若欲读取标签的UID与程序中设置的UID一致,则可以成功读取该标签信息,串口监视器中会出现如图14-6所示内容。

6-6读取成功时串口监视器输出的实验结果

 4、编写代码,实现向RFID标签中写入信息的功能

1)在新建的Arduino程序窗口中输入如下代码:

#include <SPI.h>

#include <MFRC522.h>

#define RST_PIN 5           

#define SS_PIN 4           

MFRC522 mfrc522(SS_PIN, RST_PIN);

MFRC522::MIFARE_Key key;//定义密钥

void setup() {

    MFRC522::StatusCode status;

    Serial.begin(115200);

    SPI.begin();

    mfrc522.PCD_Init();

    //使用0xFF作为基本密钥

    for (byte i = 0; i < 6; i++) {

        key.keyByte[i] = 0xFF;

    }

    Serial.println();

    Serial.println(F("Scan a tag to write to it."));

}

void loop() {

    if ( ! mfrc522.PICC_IsNewCardPresent())

        return;

    if ( ! mfrc522.PICC_ReadCardSerial())

        return;

    //显示标签的基本信息

    Serial.print(F("Card UID:"));

    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);

    Serial.println();

    Serial.print(F("PICC type: "));

    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);

    Serial.println(mfrc522.PICC_GetTypeName(piccType));

    //判断卡的类型,该程序仅支持MIFARE Classic cards

    if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI

        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K

        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {

        Serial.println(F("This sample only works with MIFARE Classic cards."));

        return;

    }

    //定义要写入数据的位置和内容

    byte  sector= 1;   //写入位置为sector 1

    byte  blockAddr= 5; //写入位置是sector 1block 5

    //要写入的信息如下,共16字节

    byte  dataBlock[] = {

        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,

        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f  

    };

    byte trailerBlock   = 7;

    MFRC522::StatusCode status;

    byte buffer[18];

    byte size = sizeof(buffer);

    //授权使用密钥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));

        return;

    }

    //显示sector 1当前的数据,即写入前的数据

    Serial.println(F("Current data in sector:"));

    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);

    Serial.println();

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

    Serial.println(F(" ..."));

    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);

    if (status != MFRC522::STATUS_OK) {

        Serial.print(F("MIFARE_Read() failed: "));

        Serial.println(mfrc522.GetStatusCodeName(status));

    }

    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));

    dump_byte_array(buffer, 16); Serial.println();

    Serial.println();

    //授权使用密钥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));

        return;

    }

    //写入信息到相应位置

    Serial.print(F("Writing data into block ")); Serial.print(blockAddr);

    Serial.println(F(" ..."));

    dump_byte_array(dataBlock, 16); Serial.println();

    status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);

    if (status != MFRC522::STATUS_OK) {

        Serial.print(F("MIFARE_Write() failed: "));

        Serial.println(mfrc522.GetStatusCodeName(status));

    }

    Serial.println();

    //再次读取写入后的该位置数据信息

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

    Serial.println(F(" ..."));

    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);

    if (status != MFRC522::STATUS_OK) {

        Serial.print(F("MIFARE_Read() failed: "));

        Serial.println(mfrc522.GetStatusCodeName(status));

    }

    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));

    dump_byte_array(buffer, 16); Serial.println();

    //通过逐字节判断写入是否有误

    Serial.println(F("Checking result..."));

    byte count = 0;

    for (byte i = 0; i < 16; i++) {

        // Compare buffer (= what we've read) with dataBlock (= what we've written)

        if (buffer[i] == dataBlock[i])

            count++;

    }

    Serial.print(F("Number of bytes that match = ")); Serial.println(count);

    if (count == 16) {

        Serial.println(F("Success"));

    } else {

        Serial.println(F("Failure, no match"));

        Serial.println(F("  perhaps the write didn't work properly..."));

    }

    Serial.println();

    //读取整个sector的信息

    Serial.println(F("Current data in sector:"));

    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);

    Serial.println();

    mfrc522.PICC_HaltA();

    mfrc522.PCD_StopCrypto1();

}

void dump_byte_array(byte *buffer, byte bufferSize) {

    for (byte i = 0; i < bufferSize; i++) {

        Serial.print(buffer[i] < 0x10 ? " 0" : " ");

        Serial.print(buffer[i], HEX);

    }

}

2)将USB线缆插入计算机,待程序上传成功后打开串口监视器,将RFID标签靠近读卡器,在串口监视器中观察是否成功写入数据信息,正确的结果如图14-7所示内容。

6-7写入成功时串口监视器输出的实验结果