arduino + RC522 读写字符串数据

arduino + RC522 读写字符串数据

  • 实验描述
  • RFID模块基本知识
    • MFRC522库
    • NXP_MFRC522读写器(Proximity Coupling Device)
    • PICC(Proximity Integrated Circuit Card)
  • 硬件连接
  • 程序流程图
  • 程序源码

实验描述

本实验将会实现一个通过串口发送命令读取信息或者写入特定信息到指定位置,我目前做的是实现对某药品名称、性状、用法用量等具体信息的存取,因此,此处我实现的是对药品名称进行读写,我在代码中定义了一个有关药品信息的结构体,读者可以通过在其中添加成员来实现添加信息项的目的,在此记录下来供以后参考,由于本人菜鸟一个且本实验还未成熟,大佬发现有错误烦请指正。

RFID模块基本知识

MFRC522库

本实验基于MFRC522库进行开发,需要先加载此库文件。

NXP_MFRC522读写器(Proximity Coupling Device)

恩智浦生产的一种工作在13.56MHz电磁场下的RFID读卡器,可以读取MIFARE 4K、MIFARE 1K、MIFARE Mini等卡片。

PICC(Proximity Integrated Circuit Card)

一种使用ISO 14443A接口的RFID卡片,例如:MIFARE、NTAG203。
MIFARE 经常使用的又有MIFARE 4K,MIFARE 1K和MIFARE Mini几种,由于我使用的时MIFARE 1K,因此我下面以MIFARE 1K为例进行介绍。
MIFARE 1K共有16个扇区,每个扇区4个块,每个块可以存储16个字节,因此似乎我们一共有16 x 4 x 16 Byte的存储空间,即1KB。然而事实并非如此,每个扇区中都固定最后一个块(称之为Sector Trailer)我们不能存储数据,而被用来存储整个扇区访问控制有关的数据。具体每个字段是什么意思我也不是也太清楚,可以查阅一下恩智浦公司相关产品的数据手册(但是我知道对每个块进行读写时需要使用Key B进行验证,验证通过后才能完成读写)Key B出厂时默认设置为FF FF FF FF FF FF。每个扇区中最后一个块的内字段定义如下:

Bytes 0-5 Key A
Bytes 6-8 Access Bits
Bytes 9 User data
Bytes 10-15 Key B (or user data)

而对于扇区0来说,它的第0块存储的为该卡片的序列号等信息,因此我们也是只能读取不能写入用户新数据。因此MIFARE 1K实际可用容量为[(15 x 3)+2 ] x 16 = 752 B,其余MIFARE 4K 和 MIFARE Mini类似。因此,对于一个MIFARE 1K 我们实际可用的空间分布为:

Block0 UID、Type、etc…
Block1 UserData
Block2 UserData
Block3 Sector trailer
Block4 UserData
Block5 UserData
Block6 UserData
Block7 Sector trailer
Block8 UserData
Block9 UserData
Block10 UserData
Block11 Sector trailer
Block12 UserData
Block13 UserData
Block14 UserData
Block15 Sector trailer

硬件连接

MFRC522 Arduino UNO
RST 9
SDA(SS) 10
MOSI 11 / ICSP-4
MISO 12 / ICSP-1
SCK 13 / ICSP-3

程序流程图

主程序运行过程:

Created with Raphaël 2.2.0 开始 等待输入命令 指令格式是否正确? 0(Read)? 读数据 写数据 yes no yes no

程序源码

/*
 * Write and Read personal data of a MIFARE RFID card using a RFID-RC522 reader
 * Uses MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT. 
 * -----------------------------------------------------------------------------------------
 *             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
 *
 * Hardware required:
 * Arduino
 * PCD (Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
 * PICC (Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
 * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com. 
 */

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

typedef struct{
  byte DrugName[48];  //药品名称
  byte Dosage[12];    //用法用量
  byte Remaining[4];  //剩余量
}DrugInfo;

#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;
MFRC522::StatusCode status;

DrugInfo drugInfo;      //实例化一个药品信息的结构体变量

byte block;
byte len;

const byte drugNameBlockAddr[3] = {1,2,4};   //药品名称的存储地址

void setup() {
  Serial.begin(9600);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;    // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  Serial.println(F("Write and Read personal data on a MIFARE PICC "));
}

void loop(){
  char cmd = ' ';
  byte count = 0;
  while(Serial.read() >= 0);  //清空在PICC卡读写期间的串口数据
  Serial.println("please input a command(0:read; 1:write):");
  while(Serial.available() <= 0);  //等待指令输入
  delay(10);                       //等待数据全部进入缓冲区
  if(Serial.available() != 1)
  {
    Serial.println("error: Invalid command!");
    while(Serial.read() >= 0);
    return;
  }
  cmd = (char)Serial.read();
  if(cmd != '0' && cmd != '1')
  {
    Serial.println("error: Invalid command!");
    return;
  }

  
  /*###############################################################################################################################*/
  if(cmd == '0')
  {
    //read a PICC card
    Serial.println("Waiting for the appearance of the PICC card in one minute(read)...");

    // Look for new cards
    while ( ! mfrc522.PICC_IsNewCardPresent()) 
    {
      delay(1000);
      if(count++>60)
      {
        Serial.println("Waiting timeout...");
        count = 0;
        return;
      }
    }

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
      return;
    }

    Serial.println(F("**Card Detected:**"));


    mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

    //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex

    Serial.print(F("Drug Name: "));

    len = 18;
    for(uint8_t i = 0; i < sizeof(drugNameBlockAddr);i++)
    {
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, drugNameBlockAddr[i], &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Authentication failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }

      status = mfrc522.MIFARE_Read(drugNameBlockAddr[i], &drugInfo.DrugName[i*16], &len);
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Reading failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
    }

    //PRINT FIRST NAME
    for (uint8_t i = 0; i < sizeof(drugInfo.DrugName); i++)
    {
      Serial.write(drugInfo.DrugName[i]); 
    }
    Serial.print(" ");

    Serial.println(F("\n**End Reading**\n"));

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

  }
  /*###############################################################################################################################*/
  else if(cmd == '1')
  {
    //write a PICC card
    Serial.println("Waiting for the appearance of the PICC card in one minute(write)...");
    // Look for new cards
    while( ! mfrc522.PICC_IsNewCardPresent())
    {
      delay(1000);
      count++;
      if(count > 60)
      {
        count = 0;
        Serial.println("Waiting timeout...");
        return;
      }
    }
   // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
     return;
    }
    Serial.print(F("Card UID:"));    //Dump UID
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
      Serial.print(mfrc522.uid.uidByte[i], HEX);
    }
    Serial.print(F(" \nPICC type: "));   // Dump PICC type
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));
    
    for(byte i = 0; i < sizeof(drugInfo.DrugName); i++) drugInfo.DrugName[i] = ' ';
    while(Serial.read() >= 0);
    Serial.println("please input drug name(Less than 48 characters):");
    
    while(Serial.available()<=0)//等待输入
    {
      delay(1000);
      count++;
      if(count > 300)
      {
        Serial.println("No drug name entered");
        count = 0;
        return;
      }
    }
    delay(10);//等待数据全部进入缓冲区
    int length = Serial.available();
    for(byte i = 0; i < length; i++)
    {
      drugInfo.DrugName[i] = Serial.read();
    }

    for(byte i = 0; i < sizeof(drugNameBlockAddr); i++)
    {
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, drugNameBlockAddr[i], &key, &(mfrc522.uid));
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("PCD_Authenticate() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else Serial.println(F("PCD_Authenticate() success: "));

      // Write block
      status = mfrc522.MIFARE_Write(drugNameBlockAddr[i], &drugInfo.DrugName[i*16], 16);
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("MIFARE_Write() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else Serial.println(F("MIFARE_Write() success: "));
    }
    
    /*###############################################################################################################################*/

    Serial.println(" ");
    mfrc522.PICC_HaltA(); // Halt PICC
    mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
  }
}

你可能感兴趣的:(Arduino,arduino,RC522,RFID)