Blog

Blog

PHODAL

Arduino NFC实验,Arduino读取RFID信息

因为偶然的关系需要用到NFC来hack某些东西,这里用到的是DFROBOT的NFC模块,用的是串口通信的方法。

NFC

NFC近场通信(Near Field Communication,NFC),又称近距离无线通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输(在十厘米内)交换数据。这个技术由免接触式射频识别(RFID)演变而来,并向下兼容RFID,最早由Sony和Philips各自开发成功,主要用于手机等手持设备中提供M2M(Machine to Machine)的通信。由于近场通讯具有天然的安全性,因此,NFC技术被认为在手机支付等领域具有很大的应用前景。

Arduino NFC

PN532是NXP最近推出的一款NFC芯片,支持读卡器模式和卡模式(需要卡芯片Smart MX),支持TypeA、TypeB、TypeC三个标准,内部带一个MCU51,支持命令方式,可以直接跟PC机串口连接就成为一个RFID读卡器,简单方便,成本低,性能好,是RFID发展的一个趋势。

读卡器通过串口和电脑连接,上位机可以使用libnfc,libnfc是一个开源的软件,功能特别强大,实现了很多nfc的功能。

DFROBOT NFC

The NFC Module for Arduino is designed to extend this powerful feature for your project or application based on Arduino.It integrates a PN532 NFC controller from Philips.The driver interface for this product is UART interface of the microcontroller. So it's possible for you to test it via a USB to UART converter directly. On the other hand, for the applications with microcontroller, the module provides an event for your processor when detects the NFC tags, stickers, key fobs, or cards via high speed serial uart.

简介可以看这个 http://www.dfrobot.com/wiki/index.php/NFC_Module_for_Arduino_(SKU:DFR0231)

用的是串口通信的方式。

示例代码如下,可以读取UID

const unsigned char wake[24]={
  0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
  0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
  0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_ACK[25] = {
  0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, \
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
unsigned char old_id[5];

unsigned char receive_ACK[25];//Command receiving buffer
//int inByte = 0;               //incoming serial byte buffer

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define print1Byte(args) Serial1.write(args)
#define print1lnByte(args)  Serial1.write(args),Serial1.println()
#else
#include "WProgram.h"
#define print1Byte(args) Serial1.print(args,BYTE)
#define print1lnByte(args)  Serial1.println(args,BYTE)
#endif

void setup()
{
  Serial.begin(9600);   // open serial with PC
  Serial1.begin(115200);    //open serial1 with device
  //Serial2.begin(115200);
  wake_card();
  delay(100);
  read_ACK(15);
  delay(100);
  display(15);


}

void loop()
{
  send_tag(); 
  read_ACK(25);
  delay(100);
  if (!cmp_id ()) {
    if (test_ACK ()) {
      display (25);
      delay (100);
    }
  }
  copy_id ();
}


void copy_id (void) 
{//save old id
  int ai, oi;
  for (oi=0, ai=19; oi<5; oi++,ai++) {
    old_id[oi] = receive_ACK[ai];
  }
}


char cmp_id (void) 
{//return true if find id is old
  int ai, oi;
  for (oi=0,ai=19; oi<5; oi++,ai++) {
    if (old_id[oi] != receive_ACK[ai])
      return 0;
  }
  return 1;
}


int test_ACK (void) 
{// return true if receive_ACK accord with std_ACK
  int i;
  for (i=0; i<19; i++) {
    if (receive_ACK[i] != std_ACK[i])
      return 0;
  }
  return 1;
}


void send_id (void) 
{//send id to PC
  int i;
  Serial.print ("ID: ");
  for (i=19; i<= 23; i++) {
    Serial.print (receive_ACK[i], HEX);
    Serial.print (" ");
  }
  Serial.println ();
}


void UART1_Send_Byte(unsigned char command_data)
{//send byte to device
  print1Byte(command_data);
#if defined(ARDUINO) && ARDUINO >= 100
  Serial1.flush();// complete the transmission of outgoing serial data 
#endif
}


void UART_Send_Byte(unsigned char command_data)
{//send byte to PC
  Serial.print(command_data,HEX);
  Serial.print(" ");
}


void read_ACK(unsigned char temp)
{//read ACK into reveive_ACK[]
  unsigned char i;
  for(i=0;i<temp;i++) {
    receive_ACK[i]= Serial1.read();
  }
}


void wake_card(void)
{//send wake[] to device
  unsigned char i;
  for(i=0;i<24;i++) //send command
    UART1_Send_Byte(wake[i]);
}


void firmware_version(void)
{//send fireware[] to device
  unsigned char i;
  for(i=0;i<9;i++) //send command
    UART1_Send_Byte(firmware[i]);
}


void send_tag(void)
{//send tag[] to device
  unsigned char i;
  for(i=0;i<11;i++) //send command
    UART1_Send_Byte(tag[i]);
}


void display(unsigned char tem)
{//send receive_ACK[] to PC
  unsigned char i;
  for(i=0;i<tem;i++) //send command
    UART_Send_Byte(receive_ACK[i]);
  Serial.println();
}

PN532 NFC常用指令

唤醒: 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 03 FD D4 14 01 17 00 也就是我们在代码中看到的

 const unsigned char wake[24]={
  0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module

唤醒完后,会返回

 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00

获取UID: 00 00 FF 04 FC D4 4A 01 00 E1 00

上面的示例代码调用了send_tag后发送

     const unsigned char tag[11]={
    0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command

返回了下面的数据

  0 0 FF 0 FF 0 0 0 FF C F4 D5 4B 1 1 0 4 8 4 F5 FC 71 5 67 0

在上面的数据中

  F5 FC 71 5

身份校验: 00 00 FF LEN LCS D4 40 01 60 Addr FF FF FF FF FF FF UID DCS 00 (还没有试过) 读操作: 00 00 FF 05 FB D4 40 01 30 Addr DCS 00
写操作: 00 00 FF 15 EB D4 40 01 A0 Addr BlockData 4F 00


或许您还需要下面的文章:

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签