目录
一、概述
由于最近在开发关于NFC的新应用场景,所以对于这一个已经走进我们生活但是还未有深入了解的一个技术点做一个初步性的总结。其中会涉及到的内容包括NFC的基本原理、驱动代码、以及一些整合资料。
二、NFC简介
NFC 是前些年就开始流行的技术。当三星或 HTC 等智能手机公司推出他们最新的高端手机时,我们经常听到这个词。市场上几乎所有的高端手机都支持 NFC。近场通信 (NFC) 是一套针对智能手机和类似设备的标准,通过将它们相互接触或靠近(通常不超过几厘米)来建立无线电通信。这对与很多实际工作中的还需要人工手抄的部分都是有重要意义的。其中一个我们都知道的例子,新一代的身份证,大家都说他是内置芯片的,只需要刷一下就可以识别内部的信息,而且不易损坏,比之前要便利得多。这也可以当做一个商机。像现在依旧可以有很多地方可以用上NFC技术,这是一个值得思考的方向。
PN532使用指南(英文):
NXP官网链接:
什么是NFC? (NFC的原理)
近场通信 (NFC) ,全称是Near Field Communication,是一种基于射频识别 (RFID) 的技术标准,可以在短距离内以无线方式传输信息。NFC技术使得交易、交换数字内容和通过触摸连接电子设备变得更加简单,从而使全球消费者的生活更轻松、更方便。 NFC与全球已部署的数亿张非接触式卡和读卡器兼容。
NFC根据电感耦合原理运行,至少是对于短距离实施而言。这主要涉及读卡器设备通过电流穿过线圈来产生磁场。当标签(带有自己的线圈)被放置到附近时,该磁场会在标签内感应出电流——没有任何电线,甚至没有物理接触。然后,一旦初始握手完成,标签上存储的任何数据都会无线传输到读卡器。
NFC与RFID的区别:
RFID和NFC之间的主要区别在于它们的传输范围。 RFID通常用于更长的距离。例如,一些地区通过RFID自动收取道路通行费。如果RFID标签配备电源,则可以在更远的距离上进行通信。
PN532
先来介绍一下我使用的PN532模块:(也是用来读取NFC的一个集成式芯片)
主要特点:
1、易于更改模式:使用小型 SMD 拨动开关,在 IIC、SPI 和 HSU 模式之间切换变得非常容易。
2、读取距离长:读取距离变为 5~7 厘米,而上一版本 4 为 4~6 厘米。
3、可以便利的添加软件以支持 Android 手机的 NFC
对于其上的基本配置条件,没有过多的需要赘述的地方(特别注意小型 SMD 拨动开关):
三、驱动测试
可以直接访问以下链接查看github上的源代码以及示例:
可以直接通过IDE平台的库管理搜索PN532库文件然后安装,找到对应的驱动示例进行验证。
在其中有两个部分值得注意:(以下代码均取自我以运行成功的程序中,不具备普适性;如果无法适配,请根据自己的硬件设置进行调整)
第一个是启动配置,注意你硬件连接是什么就需要把模块上的小型 SMD 拨动开关进行相应的转换,电源电压推荐使用3.3V,5V使用起来发热有点严重。
// If using the breakout with SPI, define the pins for SPI communication.
#define PN532_SCK 12
#define PN532_MOSI 11
#define PN532_SS 10
#define PN532_MISO 13
// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines. Use the values below (2, 3) for the shield!
#define PN532_IRQ (2)
#define PN532_RESET (3) // Not connected by default on the NFC Shield
// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:
// Use this line for a breakout with a SPI connection:
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
// Use this line for a breakout with a hardware SPI connection. Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin.
Adafruit_PN532 nfc(PN532_SS);
// Or use this line for a breakout or shield with an I2C connection:
//Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
第二个是NFC的读取部分,它是分为两个不同的情况的,一种是4位uid,另一种是7位uid。
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
// 'uid' will be populated with the UID, and uidLength will indicate
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (success) {
// Display some basic information about the card
Serial.println("Found an ISO14443A card");
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print(" UID Value: ");
nfc.PrintHex(uid, uidLength);
Serial.println("");
if (uidLength == 4)
{
// We probably have a Mifare Classic card ...
Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
// Now we try to go through all 16 sectors (each having 4 blocks)
// authenticating each sector, and then dumping the blocks
for (currentblock = 0; currentblock < 64; currentblock++)
{
// Check if this is a new block so that we can reauthenticate
if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false;
// If the sector hasn't been authenticated, do so first
if (!authenticated)
{
// Starting of a new sector ... try to to authenticate
Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------");
if (currentblock == 0)
{
// This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!)
// or 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 for NDEF formatted cards using key a,
// but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF)
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
}
else
{
// This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!)
// or 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 for NDEF formatted cards using key a,
// but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF)
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
}
if (success)
{
authenticated = true;
}
else
{
Serial.println("Authentication error");
}
}
// If we're still not authenticated just skip the block
if (!authenticated)
{
Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate");
}
else
{
// Authenticated ... we should be able to read the block now
// Dump the data into the 'data' array
success = nfc.mifareclassic_ReadDataBlock(currentblock, data);
if (success)
{
// Read successful
Serial.print("Block ");Serial.print(currentblock, DEC);
if (currentblock < 10)
{
Serial.print(" ");
}
else
{
Serial.print(" ");
}
// Dump the raw data
nfc.PrintHexChar(data, 16);
}
else
{
// Oops ... something happened
Serial.print("Block ");Serial.print(currentblock, DEC);
Serial.println(" unable to read this block");
}
}
}
}
else
{
Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
}
}
四、测试结果
以下是我的运行结果:(第一个方框内是NFC的uid,第二个方框内是我编辑写入的标签)
如果你想通过手机去校验NFC信息是否正确,或者是手动修改NFC内的信息,又或者尝试锁定NFC标签(锁定之后不可更改,不可逆) 可以使用如下APP:(安卓和苹果都可以直接搜索NFC Tools Pro下载,这是我亲自使用过的比较稳定专业便利的NFC读写程序)
到这里其实就已经完成了NFC的基本操作, 值得一提的是NFC的稳定性,对于日常使用来说可以说一句稳定性拉满,我曾经把NFC芯片放入一个高温箱内,进行最高温度为240℃,加热时长达4小时的一个持续性高温烘烤,到最后NFC的外壳基本上已经彻底融化了,但是依旧可以读出NFC内的信息,很牛逼。
五、总结
在查找关于NFC的资料时发现它的资源还是很丰富的,并且APP开发的相对成熟了,而且是免费的。所以作为一个实际商业项目而言,如何把对其的操作程序简化,使其只满足某些特定的需求才是核心重点,例如:我只需要两个功能,一个是记录uid,记录完成之后写入一串按照一定规律变化的标签,之后在锁定它,最后再把所有这些信息自动汇总在一个平台上,其他的数据都不是我想关心的,无论是空间使用率还是芯片类型技术要点,都不需要。最匹配的就是有一个足够稳定简洁高效的驱动代码可以实现我想要的这个要求。
以上就是我关于NFC使用的一些初步总结和感想,目前来说它还是一个很有潜力的产品,最近很多RFID公司都上市了,它在进一步的改变我们的生活,更加智能化便利化,与目前智能化、去人工化的趋势相符。
挖坑:预计在将来会对RFID的读写程序进行开发(因为RFID可以远程监测相对于NFC,比较适合空间足够、需要快速获取、减少人员接触的场合),把带有特定RFID标签的设备进行远程读取并自动检测记录,类似于机场的基于芯片的那种检测,如果你经历过的话。
如果您对我所介绍的内容有任何改进的建议也欢迎告诉我!如果本文对你有帮助的话,不妨点个赞。欢迎留言讨论问题,一起讨论问题、解决问题。