风筝
发表于: 2022-3-30 17:53:13 | 显示全部楼层

在本篇文章中,我们将在三种模式下(UART、I2C和SPI)将PN532 NFC RFID模块与Arduino开发板连接。 PN532是一种NFC RFID模块,在移动支付方面很受欢迎,并且可以用作智能手机中与其他通信的工具。它可以嵌入到模块中,以便与您的Arduino项目轻松融合。


RC522模块无疑是Arduino项目中最著名的RFID模块。但PN532 NFC RFID读卡器与RC522相比具有一定的优势,尤其是在通信选项方面。在本文中,我们将看到如何根据UART、SPI和I2C 的不同通信方式将PN532 NFC RFID模块与Arduino开发板一起使用。文章末尾处我们还将在0.96英寸的OLED屏上显示NFC卡的UID。


所需的组件

●    Arduino Nano开发板

●    PN532 NFC RFID模块

●    0.96寸I2C OLED显示屏

●    连接跳线

●    面包板


NFC简介

在了解PN532之前,让我们先了解一下什么是 NFC 技术以及它是如何工作的。


什么是NFC?

近场通信 (NFC) ,全称是Near Field Communication,是一种基于射频识别 (RFID) 的技术标准,可以在短距离内以无线方式传输信息。

nfc.jpg


NFC技术使得交易、交换数字内容和通过触摸连接电子设备变得更加简单,从而使全球消费者的生活更轻松、更方便。 NFC与全球已部署的数亿张非接触式卡和读卡器兼容。


NFC是如何工作的?

NFC根据电感耦合原理运行,至少是对于短距离实施而言。这主要涉及读卡器设备通过电流穿过线圈来产生磁场。

how-NFC-Works.jpg


当标签(带有自己的线圈)被放置到附近时,该磁场会在标签内感应出电流——没有任何电线,甚至没有物理接触。然后,一旦初始握手完成,标签上存储的任何数据都会无线传输到读卡器。


RFID和NFC之间的区别

RFID和NFC之间的主要区别在于它们的传输范围。 RFID通常用于更长的距离。例如,一些地区通过RFID自动收取道路通行费。如果RFID标签配备电源,则可以在更远的距离上进行通信。

RFID-vs-NFC.jpg


然而,NFC的最大范围最多只有几厘米。在大多数与智能手机相关的应用程序中,您会发现该软件只有在接触的情况下才会启动通信。 NFC设备可以充当读卡器或标签。这种双向功能允许您将一个硬件(例如您的智能手机)用于各种不同的应用程序。


NFC的主要应用

●    移动支付; Apple Pay NFC、谷歌钱包

●    点击配对;只需轻按即可配对蓝牙设备,无需手动输入

●    在实体产品中嵌入数字体验; NFC的小尺寸使其能够嵌入到物理产品中,从而在交互时提供独特的体验

●    安全

●    密码替换

●    产品认证


PN532 NFC模块

PN532是NXP公司推出的NFC控制器,基于80C51微控制器,可实现13.56 MHz的非接触式通信。此外,对MIFARE Classic 1K/MIFARE Classic 4K卡的支持允许双向传输速度高达424 kbit/s。

PN532 NFC 模块

PN532 NFC 模块


它带有40 Kb的ROM和1Kb的RAM,并且可以用于模拟ISO14443卡。 ISO/IEC 14443系列标准描述了用于国际交换的身份证或对象的参数。


PN532 NFC模块的主要特点:

●    基于具有40 KB的ROM和1 KB的RAM的80C51微控制器内核

●    高度集成的解调器和解码器

●    集成射频电平检测器

●    支持 ISO/IEC 14443A/MIFARE

●    支持 ISO/IEC 14443B(仅限读写器模式)

●    在读卡器/写卡器模式下工作距离可达50毫米,用于与ISO/IEC 14443A/MIFARE、ISO/IEC 14443B 或 FeliCa 卡通信

●    NFCIP-1 的工作距离可达50毫米,具体取决于天线尺寸、调谐和电源

●    ISO/IEC 14443A/MIFARE 或 FeliCa 卡仿真模式下的操作距离约为 100mm

●    可以使用外部模拟组件在 424 kbit/s 以上的RF接口上进行通信

●    专用主机中断

●    低功耗模式

●    可编程定时器

●    晶振

●    2.7 至 5.5 V 电源工作范围


通信模式的选择

PN532 NFC模块的一大优势是它可以使用不同的协议与Arduino进行通信,例如UART、I2C或SPI。 这些不同的协议使用微控制器的特定引脚和库。

PN532 I2C SPI UART

PN532 I2C SPI UART


要选择通信模式,必须使用拨码开关(0-Low,1-High)配置 PN532:


SEL0
SEL1
UART
0
0
SPI
0
1
I2C
1
0

NFC RFID卡

NFC标签与任何其他RFID标签一样通过无线电波进行通信。 两个设备——NFC 标签和NFC读卡器以NFC数据交换格式交换信息。 NFC标签可能是您的ATM卡、旅行卡、地铁卡或其他卡。

NFC 标签

NFC 标签


NFC标签发送无线电波以激活接收设备中的天线。 接收方验证信息以完成信息交换。 该技术可以在非常短的距离内工作——大约 4 英寸。 NFC标签无需电池即可工作,并且从其他设备(例如智能手机)获取电力。

跳转到指定楼层
风筝
发表于: 2022-3-31 14:39:19 | 显示全部楼层

使用UART模式将PN532与Arduino连接

让我们首先通过UART串行通信方式读取NFC数据。 如下图所示将PN532连接到Arduino开发板。 GND、VCC、Tx和Rx引脚标记在模块的背面。

PN532-Arduino-UART.jpg


PN532连接到Arduino开发板的方式

●    GND(接地)<-> GND

●    Vcc(电源)<-> 5V

●    Tx <-> D3

●    Rx <-> D2

Interfacing-PN532-with-Arduino-in-UART-Mode.jpg


PN532有多种不同的通信模式,因此必须在每种情况下使用正确的库。 支持所有通信协议的库是PN532 Elechouse库。 下载zip文件夹并解压缩所有库,然后将其添加到Arduino库文件夹中。


在UART通信模式下,使用以下库。

1.  PN532_HSU库

2.  PN532_SWHSU库


复制以下代码并将其上传到 Arduino 板。

  1. #include <SoftwareSerial.h>
  2. #include <PN532_SWHSU.h>
  3. #include <PN532.h>
  4. SoftwareSerial SWSerial( 3, 2 ); // RX, TX

  5. PN532_SWHSU pn532swhsu( SWSerial );
  6. PN532 nfc( pn532swhsu );
  7. String tagId = "None", dispTag = "None";
  8. byte nuidPICC[4];

  9. void setup(void)
  10. {
  11.   Serial.begin(115200);
  12.   Serial.println("Hello Maker!");
  13.   //  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
  14.   nfc.begin();
  15.   uint32_t versiondata = nfc.getFirmwareVersion();
  16.   if (! versiondata)
  17.   {
  18.     Serial.print("Didn't Find PN53x Module");
  19.     while (1); // Halt
  20.   }
  21.   // Got valid data, print it out!
  22.   Serial.print("Found chip PN5");
  23.   Serial.println((versiondata >> 24) & 0xFF, HEX);
  24.   Serial.print("Firmware ver. ");
  25.   Serial.print((versiondata >> 16) & 0xFF, DEC);
  26.   Serial.print('.');
  27.   Serial.println((versiondata >> 8) & 0xFF, DEC);
  28.   // Configure board to read RFID tags
  29.   nfc.SAMConfig();
  30.   //Serial.println("Waiting for an ISO14443A Card ...");
  31. }


  32. void loop()
  33. {
  34.   readNFC();
  35. }


  36. void readNFC()
  37. {
  38.   boolean success;
  39.   uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  40.   uint8_t uidLength;                       // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  41.   success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  42.   if (success)
  43.   {
  44.     Serial.print("UID Length: ");
  45.     Serial.print(uidLength, DEC);
  46.     Serial.println(" bytes");
  47.     Serial.print("UID Value: ");
  48.     for (uint8_t i = 0; i < uidLength; i++)
  49.     {
  50.       nuidPICC[i] = uid[i];
  51.       Serial.print(" "); Serial.print(uid[i], DEC);
  52.     }
  53.     Serial.println();
  54.     tagId = tagToString(nuidPICC);
  55.     dispTag = tagId;
  56.     Serial.print(F("tagId is : "));
  57.     Serial.println(tagId);
  58.     Serial.println("");
  59.     delay(1000);  // 1 second halt
  60.   }
  61.   else
  62.   {
  63.     // PN532 probably timed out waiting for a card
  64.     Serial.println("Timed out! Waiting for a card...");
  65.   }
  66. }
  67. String tagToString(byte id[4])
  68. {
  69.   String tagId = "";
  70.   for (byte i = 0; i < 4; i++)
  71.   {
  72.     if (i < 3) tagId += String(id[i]) + ".";
  73.     else tagId += String(id[i]);
  74.   }
  75.   return tagId;
  76. }
复制代码

上传代码后,您可以打开串口监视器,然后将一些NFC卡靠近PN532,开始测试模块。

UART.png


在高速UART模式下,芯片只能读取4个字节的数据。 模块无法从NFC卡读取7个字节的数据。

回复

使用道具 举报

风筝
发表于: 2022-3-31 14:59:01 | 显示全部楼层

使用I2C模式将PN532与Arduino连接

现在让我们使用I2C模式读取NFC数据。 如下图所示将PN532连接到Arduino开发板。

PN532-Arduino-I2C.jpg


PN532与Arduino开发板的连接方式:

●    GND(接地)<-> GND

●    VCC(电源)<-> 5V

●    SDA(数据)<-> A4

●    SCL(时钟)<-> A5

Interfacing-PN532-with-Arduino-in-I2C-Mode.jpg


使用I2X模式进行通讯时,首先下载载PN532_I2C库并将其添加到库文件夹中。


复制以下代码并将其上传到Arduino开发板。

  1. #include <Wire.h>
  2. #include <PN532_I2C.h>
  3. #include <PN532.h>
  4. #include <NfcAdapter.h>
  5. PN532_I2C pn532_i2c(Wire);
  6. NfcAdapter nfc = NfcAdapter(pn532_i2c);
  7. String tagId = "None";
  8. byte nuidPICC[4];

  9. void setup(void)
  10. {
  11. Serial.begin(115200);
  12. Serial.println("System initialized");
  13. nfc.begin();
  14. }

  15. void loop()
  16. {
  17. readNFC();
  18. }

  19. void readNFC()
  20. {
  21. if (nfc.tagPresent())
  22. {
  23.    NfcTag tag = nfc.read();
  24.    tag.print();
  25.    tagId = tag.getUidString();
  26. }
  27. delay(5000);
  28. }
复制代码

上传代码后,您可以打开串口监视器,然后将一些NFC卡靠近PN532来测试模块。 在I2C模式下,芯片能够从不同的NFC标签读取4字节和7字节的数据。

I2C.png


使用SPI模式将PN532与Arduino连接

现在让我们使用SPI模式读取NFC数据。 在SPI模式下,需要连接多根导线。如下图所示将PN532连接到Arduino。

PN532-Arduino-SPI.jpg


PN532与Arduino开发板的连接方式:

●    VCC(电源)<-> 5V

●    RST(复位)<-> 9

●    GND(接地)<-> GND

●    MISO(主输入从输出)<-> 11

●    MOSI(主输出从输入)<-> 12

●    SCK(串行时钟)<-> 13

●    SS(从机选择)<-> 10

Interfacing-PN532-with-Arduino-in-SPI-Mode.jpg


在使用SPI模式进行通信时,首先下载PN532_SPI库并将其添加到库文件夹中。


复制以下代码并将其上传到Arduino开发板。

  1. // for SPI Communication
  2. #include <SPI.h>
  3. #include <PN532_SPI.h>
  4. #include <PN532.h>
  5. #include <NfcAdapter.h>
  6. PN532_SPI interface(SPI, 10); // create a PN532 SPI interface with the SPI CS terminal located at digital pin 10
  7. NfcAdapter nfc = NfcAdapter(interface); // create an NFC adapter object
  8. String tagId = "None";

  9. void setup(void)
  10. {
  11. Serial.begin(115200);
  12. Serial.println("System initialized");
  13. nfc.begin();
  14. }

  15. void loop()
  16. {
  17. readNFC();
  18. }

  19. void readNFC()
  20. {
  21. if (nfc.tagPresent())
  22. {
  23.    NfcTag tag = nfc.read();
  24.    tag.print();
  25.    tagId = tag.getUidString();
  26. }
  27. delay(5000);
  28. }
复制代码

4 字节和7字节NFC卡在SPI模式下也能正常工作。

SPI.png

回复

使用道具 举报

风筝
发表于: 2022-3-31 15:13:29 | 显示全部楼层

使用OLED显示屏制作便携式NFC扫描仪

我们可以使用PN532和Arduino开发板制作一个便携式NFC扫描仪模块。为了显示数据,我们可以在电路中添加一个0.96寸I2C OLED显示屏,如下图所示。

PN532-Arduino-I2C-OLED.jpg


根据电路图将PN532模块和OLED显示屏连接到Arduino开发板。


对于这个便携式NFC扫描仪,我们没有使用上面的库。而是采用了最新的Adafruit PN532库。该库是为Adafruit PN532 NFC/RFID分线板编写的,仅支持I2C或SPI模式下与Arduino UNO/Nano开发板一起使用。


除此之外,我们还需要一些其他库。下载以下库并通过库管理器将它们添加到Arduino IDE:

1.   Adafruit PN532 库

2.   Adafruit GFX 库

3.   SSD1306 OLED库


复制以下代码并将其上传到Arduino开发板。

  1. #include <Wire.h>
  2. #include <SPI.h>
  3. #include <Adafruit_GFX.h>
  4. #include <Adafruit_SSD1306.h>
  5. #include <Adafruit_PN532.h>

  6. #define PN532_IRQ   (2)
  7. #define PN532_RESET (3)  // Not connected by default on the NFC Shield

  8. #define SCREEN_WIDTH 128 // OLED display width, in pixels
  9. #define SCREEN_HEIGHT 64 // OLED display height, in pixels
  10. #define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
  11. #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32;

  12. Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

  13. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

  14. void setup(void)
  15. {
  16.   Serial.begin(115200);
  17.   while (!Serial) delay(10); // for Leonardo/Micro/Zero
  18.   Serial.println("Hello!");

  19.   nfc.begin();

  20.   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
  21.   {
  22.     Serial.println(F("SSD1306 allocation failed"));
  23.     for (;;); // Don't proceed, loop forever
  24.   }

  25.   uint32_t versiondata = nfc.getFirmwareVersion();
  26.   if (! versiondata)
  27.   {
  28.     Serial.print("Didn't find PN53x board");
  29.     while (1); // halt
  30.   }
  31.   
  32.   // Got ok data, print it out!
  33.   Serial.print("Found chip PN5");
  34.   Serial.println((versiondata>>24) & 0xFF, HEX);
  35.   Serial.print("Firmware ver. ");
  36.   Serial.print((versiondata>>16) & 0xFF, DEC);
  37.   Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);

  38.   display.clearDisplay();
  39.   display.setCursor(0, 0); //oled display
  40.   display.setTextSize(1);
  41.   display.setTextColor(WHITE);
  42.   display.print("Found chip PN5");
  43.   display.print((versiondata >> 24) & 0xFF, HEX);

  44.   display.setCursor(0, 20); //oled display
  45.   display.setTextSize(1);
  46.   display.setTextColor(WHITE);
  47.   display.print("Firmware ver. ");
  48.   display.print((versiondata >> 16) & 0xFF, DEC);
  49.   display.print(".");
  50.   display.print((versiondata >> 8) & 0xFF, DEC);
  51.   
  52.   nfc.setPassiveActivationRetries(0xFF);
  53.   
  54.   // configure board to read RFID tags
  55.   nfc.SAMConfig();
  56.   
  57.   Serial.println("Waiting for an ISO14443A card");

  58.   display.setCursor(0, 40); //oled display
  59.   display.setTextSize(1);
  60.   display.setTextColor(WHITE);
  61.   display.print("Waiting for NFC Card");
  62.   display.display();

  63. }

  64. void loop(void)
  65. {
  66.   boolean success;
  67.   uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  68.   uint8_t uidLength;        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  69.   

  70.   success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  71.   
  72.   if (success) {
  73.     Serial.println("Found a card!");
  74.     Serial.print("UID Length: ");
  75.     Serial.print(uidLength, DEC);
  76.     Serial.println(" bytes");
  77.     Serial.print("UID Value: ");

  78.      display.clearDisplay();
  79.     display.setCursor(10, 0); //oled display
  80.     display.setTextSize(1);
  81.     display.setTextColor(WHITE);
  82.     display.print("UID Length:");
  83.     display.print(uidLength, DEC);
  84.     display.print(" bytes");

  85.     display.setCursor(35, 20); //oled display
  86.     display.setTextSize(1);
  87.     display.setTextColor(WHITE);
  88.     display.println("UID Value: ");
  89.     display.setCursor(5, 35); //oled display

  90.    
  91.     for (uint8_t i=0; i < uidLength; i++)
  92.     {
  93.    
  94.       Serial.print(" 0x");
  95.       Serial.print(uid[i], HEX);
  96.        display.print(" 0x");
  97.       display.print(uid[i], HEX);
  98.       display.display();
  99.     }
  100.     Serial.println("");
  101.   // Wait 1 second before continuing
  102.   delay(1000);
  103.   }
  104.   else
  105.   {
  106.     // PN532 probably timed out waiting for a card
  107.     Serial.println("Timed out waiting for a card");
  108.   }
  109. }
复制代码

代码上传成功后,就可以开始测试了。 OLED显示屏将打印输出固件版本为1.6,并要求扫描卡。

Portable-NFC-Scanner.jpg


现在将一些NFC卡放在PN532 NFC电路板附近。 NFC卡可以是您的银行卡或旅行卡或一些NFC测试卡。 PN532模块将读取字节长度以及UID值并将它们显示在OLED屏上。

4-Bytes.jpg


字节长度可能是4字节或7字节,具体取决于 NFC 卡的类型。

7-bytes.jpg


如果您不希望项目使用OLED显示屏,可以在串口监视器上显示UID值和字节长度。

SPI-Main.png

回复

使用道具 举报

schwarz
发表于: 2022-5-17 23:03:17 | 显示全部楼层

风筝 发表于 2022-3-31 14:59
使用I2C模式将PN532与Arduino连接现在让我们使用I2C模式读取NFC数据。 如下图所示将PN532连接到Arduino开发 ...

您好,我使用和您一样的pn532,按照您的配置i2c模式,但是使用的arduino是leonardo版本,SDA和SCL的管脚也和您连接的方式一样分别是A4和A5,但是我的Vcc和GND接口是直接接入A3(Vcc)和A2(GND),我复制了您给出的代码执行,也在您的代码中添加上了共给pn532的Vcc和GND的管脚的高低电压,程序编译上传也通过了,pn532的工作指示灯也亮起,但是打开串口监视器没有任何输出,甚至连在set up函数中的System initialized信息都没有接收到,请问是因为我使用的arduino的版本和您不一样导致的问题吗?我也注意到您的代码中没有声明A5,A4管脚的输入状态声明,请问会是这个问题吗?
回复

使用道具 举报

风筝
发表于: 2022-5-18 08:37:23 | 显示全部楼层

schwarz 发表于 2022-5-17 23:03
您好,我使用和您一样的pn532,按照您的配置i2c模式,但是使用的arduino是leonardo版本,SDA和SCL的管脚 ...

首先确认串口是否工作正常,打印输出数据。如果串口工作正常,查看I2C硬件连接
回复

使用道具 举报

zhangyubiao
发表于: 2023-3-14 16:14:14 | 显示全部楼层

no matching function for call to 'NfcAdapter::NfcAdapter(PN532_I2C&)'
您好,IIC连接中遇到这个问题怎么解决呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1479



手机版|

GMT+8, 2024-3-28 23:52 , Processed in 0.097228 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表