当前位置: 首页 > 知识库问答 >
问题:

如何使用 PN532 读取无源 NFC/RFID 单元?

巩子实
2023-03-14

我从易贝买了一个红色的“ELECHOUSE V3”套件,里面有一张白色的卡和一个蓝色的钥匙链应答器,我写了一个C程序,可以创建和解码数据包,我可以向它发送命令,它用a C数据包来响应,我可以读取版本和状态。我没有使用任何RFID库,我只是使用普通C语言并制作自己的简单库,因为我想理解它,我想为真正想理解它的人发布一个简单的单个文件演示,而不是仅仅使用一些arduino库或其他什么。这就是我没有问的所有问题。

所以我要问的问题是:

扫描无源(非供电)转发器的确切命令是什么?我不知道它们是什么类型,但它们是随套件一起提供的,可能是ISO 14443/14443A。

实际上,我在三星Galaxy S4上尝试了标签,它说它们是ISO 14443-3A NXP MIFARE经典1K - 不支持。但它仍然显示它们的序列号。

扫描所有支持的卡类型的确切命令是什么?

要发送一个命令,我像这样使用我的函数:send cmd(" 0x4A 0x 01 0x 00 ");(0xD4的TFI自动添加到命令中,前同步码/len/LCS/校验和都被计算和处理。)

我确实为我的命令返回了ACKS,但不知道要发送哪些命令来扫描卡片或读取它们。

如果我能让PN532向我吐出卡片扫描数据,我应该能够使用PN532数据表解析它。

非常感谢,

耶西

共有1个答案

房育
2023-03-14

啊好的..在尝试了数据手册中显示的所有相关内容都没有成功之后,我将业余无线电调到13.56Mhz CW/LSB,但什么也听不到..所以为了好玩,我尝试了RFRegulationTest命令,这就解开了整个问题!似乎是一个测试命令,它打开发射机,并让它一直开着,直到你发出另一个命令...但是它会根据需要初始化一些东西!

因此,以下是使恩智浦NP532扫描卡所需的命令: (我以115200bps的速度使用RS232,但其他接口应该类似。

您发送给它:

0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0xFF 0x03 0xFD 0xD4 0x58 0x00 0xD4

然后你会得到一个ACK,发射机将打开:0x00 0x00 0xFF 0x00 0xFF 0x00

此时,发射器将打开。也许让它在 100mS 或其他情况下这样做,然后您可以开始扫描卡:

0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0xFF 0x04 0xFC 0xD4 0x4A 0x02 0x00 0xE0

然后,芯片将打开无线电发射器,开始扫描卡,直到卡进入范围,然后它读取序列号,关闭发射器,并给你一个包,其中包含:

0x4B、0x01/0x02(取决于检测到的是1张还是2张卡),然后是关于卡的各种信息,如其序列号。

给定0x4A 0x02 0x00命令时,您还可以通过将尝试次数设置为低于0xFF的数字来设置它将尝试的最大次数,如下所示:

sendcmd("0x32 0x05 0xFF 0x01 0x10")

在这种情况下,当您发出 read 命令 (0x4A 0x02 0x00) 时,它会尝试几分之一秒(0x10 次),然后放弃并发送包含以下内容的数据包:

0x4B, 0x00 

意思是“找到卡片:零”

有关所有详细信息,请参阅数据表,它确实告诉您您需要知道的所有信息,除了在运行 rf test 命令之前,我永远无法弄清楚如何启用发射器。

不管怎样,只要一秒钟反复发送第二个命令几次,如果你愿意的话,可以慢一点,每次发送命令时,它都会扫描并告诉你是否有卡在范围内!

或者,如果您将重试设置为 0xFF那么它将永远尝试,直到检测到卡,然后您只需在找到卡时重新发送扫描卡命令。

0xFF的长字符串只是为了唤醒设备,因为它进入睡眠状态,错过了您发送的前几个字节。

我给出的以一堆0xFF开头的发送内容的示例是整个完整的数据包,包括前导码、长度字段、校验和和计算的所有内容。您可以直接发送它们以使其扫描卡片。

初始RF测试命令和重试设置命令只需要在通电时运行一次,之后只需根据需要重新发送读取命令即可。

我的PN532芯片报告为版本:1.6

这是我的小示例程序

(我从SO帖子中提取的RS232初始化部分——感谢写这篇文章的人!)

(这是针对Linux的。编译 with gcc nfc.c -o nfc.e )

(应该能够将其移植到任何平台,您只需要处理串行端口 - 其余的都是独立于平台的。

(还请注意,这只是扫描卡并返回序列号/NFCID,仅适用于被动模式下106kbps的Mifare、ISO/IEC14443-3 A型卡。如果你想真正读/写卡上的内存,你必须写更多的代码,但这至少说明了开始需要什么以及命令结构是如何工作的,并提供了一些发送和解码代码的便捷例程g包。)

#include <errno.h>
#include <fcntl.h> 
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int debug=0;
int fd;
void init_rs232(void);
void sendpacket(unsigned char * payload, int len);
void sendcmd(char * payload);
int main(void)
{
    printf("Welcome!\n");
    init_rs232();
    int waitfor;
#define PACKET 1
#define ACK 2
    sendcmd("0x58 0x00");waitfor=ACK; //RFRegulationTest -- This command is used for radio regulation test. 
    int cstate=0;   //Chat state, config state, whatever..
    int lc=0;
    while(1)
    {
        lc++;   //Send a scan command every second or so.
        if(lc>1000)
        {
            lc=0;
            sendcmd("0x4A 0x02 0x00");  //InListPassiveTarget -- The goal of this command is to detect as many targets (maximum MaxTg) as possible (max two) in passive mode.
        }

        if(cstate==1)   //ACK's set the bottom bit in state, allowing it to go onto the next state.
        {
            sendcmd("0x02");waitfor=PACKET; //Read the version out of the PN532 chip.
            cstate++;
        }
        if(cstate==3)   //ACK's set the bottom bit in state, allowing it to go onto the next state.
        {
            sendcmd("0x04");waitfor=PACKET; //Get current status.
            cstate++;
        }
        if(cstate==5)
        {
            waitfor=PACKET;
            sendcmd("0x32 0x05 0xFF 0x01 0x10");//Max retries - last byte is for passive: 0=1 try, 1=2 tries, 254=255 tries, 0xFF=infinite retries.
            //If last byte is 0xFF, then unit starts scanning for cards indefinitely. As soon as it detects a card, it stops scanning and returns info.
            //If last byte is less than 0xFF, it tries scans and as soon as it finds a card returns info on it and stops trying, but
            //if it never finds a card in the specified number of retries, it gives up and returns 0x4B, 0x00 (Cards found: Zero.)
            cstate++;
        }
//Alternative way to send a new scan command each time the previous one gives up or finds a card:
//      if(cstate==7)
//      {
//          waitfor=PACKET;
//          sendcmd("0x4A 0x02 0x00");      //InListPassiveTarget
//          cstate--;
//      }


        static unsigned char buffin [1000024];
        static unsigned char buf[1],bufo[1];
        int n;
        static int bi=0;
        unsigned char len,lcs,tfi,dcs;

        bufo[0]=buf[0];
        n=read(fd,buf,sizeof(buf));
        if(n!=0)
        {
            if(n>0)
            {
                if(bi<1000000)
                {
                    static int state=0;

                    if(state==0)    //Waiting for preamble..
                    {
                        if((bufo[0]==0)&&(buf[0]==0xFF)){state=10;}
                    }
                    else if(state==10)  //Waiting for Len
                    {
                        len=buf[0];
                        state=20;
                    }
                    else if(state==20)  //Waiting for len checksum
                    {
                        if((len==0xFF)&&(buf[0]==0xFF)){printf("ERROR: BIG PACKET. Bye.\n");exit(-2);}
                        if((len==0x00)&&(buf[0]==0xFF)){state=21;}
                        else if((len==0xFF)&&(buf[0]==0x00)){state=21;}
                        else
                        {
                            lcs=buf[0]+len;
                            if(lcs){printf("ERROR: len checksum failed! 0x%02X\n",buf[0]);}
                            state=30;
                        }
                    }
                    else if(state==21)  //Waiting for the 0x00 after ack/nack..
                    {
                        state=0;
                        if(buf[0]==0x00)
                        {
                            if(bufo[0]==0xFF)
                            {
                                if(debug){printf("ACK!\n");}
                                if(waitfor==ACK){cstate=cstate|1;}
                            }
                            if(bufo[0]==0x00){printf("NACK!\n");}

                        }else{
                            printf("ERROR: Invalid length, or ack/nack missing postamble...\n");
                        }
                    }
                    else if(state==30)  //Waiting for tfi..
                    {
                        tfi=buf[0];
                        //printf("tfi=0x%02X\n",tfi);
                        dcs=tfi;
                        bi=0;
                        state=40;
                    }
                    else if(state==40)  //Saving bytes...
                    {
                        //printf("Saving payload byte 0x%02X\n",buf[0]);
                        buffin[bi++]=buf[0];
                        dcs=dcs+buf[0];
                        if(bi>=len){state=50;}
                    }
                    else if(state==50)  //Calculating the checksum..
                    {
                        state=0;
                        dcs=dcs+buf[0];
                        if(dcs)
                        {
                            printf("ERROR: Data Checksum Failed! (0x%02X)\n",dcs);
                        }else{
                            if(waitfor==PACKET){cstate=cstate|1;}
                            //printf("Good Packet: tfi=0x%02X, len=%d\n",tfi,len-1);
                            if(tfi==0xD5)
                            {
                                if(buffin[0]==0x03){printf("PN532 Version: %d.%d, features:%d\n",buffin[2],buffin[3],buffin[4]);}
                                if(buffin[0]==0x05)
                                {

                                    printf("Status: Last Error:%d, Field:%d, Targets:%d, SAM Status:0x%02X\n",buffin[1],buffin[2],buffin[3],buffin[len-2]);
                                    static char bitrates[255][10]={"106kbps","212kbps","424kbps"};
                                    static char modtypes[255][100];
                                    strcpy(modtypes[0x00],"Mifare, ISO/IEC14443-3 Type A, ISO/IEC14443-3 Type B, ISO/IEC18092 passive 106 kbps");
                                    strcpy(modtypes[0x10],"FeliCa, ISO/IEC18092 passive 212/424 kbps");
                                    strcpy(modtypes[0x01],"ISO/IEC18092 Active mode");
                                    strcpy(modtypes[0x02],"Innovision Jewel tag");
                                    if(buffin[3]==1){printf("Target %d: rx bps:%s, tx bps:%s, modulation type: %s.\n",buffin[4],bitrates[buffin[5]],bitrates[buffin[6]],modtypes[buffin[7]]);}
                                    if(buffin[3]==2){printf("Target %d: rx bps:%s, tx bps:%s, modulation type: %s.\n",buffin[8],bitrates[buffin[9]],bitrates[buffin[10]],modtypes[buffin[11]]);}
                                }
                                if(buffin[0]==0x4B)
                                {
                                    printf("FOUND %d CARDS!\n",buffin[1]);
                                    //ONLY VALID FOR Mifare/ ISO type A 106KBPS:
                                    int i,ii,iii;
                                    i=0;ii=2;
                                    while(i<buffin[1])
                                    {
                                        printf("Target # %d:", buffin[ii++]);
                                        printf("SENS_RES=0x%02X%02X, ",buffin[ii],buffin[ii+1]);ii++;ii++;
                                        printf("SEL_RES=0x%02X, ",buffin[ii++]);
                                        printf("NFCIDLength=%d, ",buffin[ii++]);
                                        printf("NFCID=");
                                        iii=0;
                                        while(iii<buffin[ii-1])
                                        {
                                            printf("%02X",buffin[ii+iii]);
                                            iii++;
                                            if(iii<buffin[ii-1]){printf(":");}
                                        }
                                        ii=ii+iii;
                                        printf("\n");
                                        i++;
                                    }

                                }
                                //Just a debugging thing for printing out the contents of valid packets.
                                //int i=0;while(i<(len-1)){printf("0x%02X, ",buffin[i++]);}printf("\n");
                            }
                            else if(tfi==0x7F)
                            {
                                printf("Received error packet 0x7F with zero size.\n");
                            }else{
                                printf("ERROR: Got unknown %d byte packet with tfi=0x%02X!\n",len-1,tfi);
                            }

                        }
                    }
                    else
                    {
                        printf("Uhoh!\n");
                    }
                    //printf("Got byte 0x%02X, now state is %d\n",(unsigned char)buf[0],state);

                }else{
                    printf("ERROR: bi=%d which is too big.. Starting over.\n",bi);
                    bi=0;
                }
            }else{
                printf("ERROR %d while reading serial port: %s\n",errno,strerror(errno));
                exit(-1);
            }
        }

        usleep(1000);

    }



    return(0);
}




void init_rs232(void)
{
    char *portname = "/dev/ttyUSB0";
    fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0)
    {
            printf("error %d opening %s: %s", errno, portname, strerror (errno));
        exit(-1);
    }

        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                printf("error %d from tcgetattr(%s)\n", errno,strerror(errno));
        exit(-1);
        }

        cfsetospeed (&tty, B115200);
        cfsetispeed (&tty, B115200);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 0;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= 0;   //This was parity
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                printf("error %d from tcsetattr(%s)\n", errno,strerror(errno));
        exit(-1);
        }
}


void sendpacket(unsigned char * payload, int len)
{
    int tfi;
    static unsigned char buffer[66000];
    int i,bo;
    unsigned char lcs,dcs;
    tfi=0xD4;
    i=0;
    bo=0;
    while(i<=8){i++;buffer[bo++]=0xFF;} //Pre-padding.. 8-800 OK, 900 too much, 7 too little. Needs to be 0xFF I guess.. Probably wakes it up.
    buffer[bo++]=0x00;          //Preamble.
    buffer[bo++]=0xFF;              //Preamble.
    len++;
    lcs=-len;               //Length Checksum.. (yes...)
    buffer[bo++]=len;
    buffer[bo++]=lcs;
    buffer[bo++]=tfi;
    dcs=tfi;
    i=0;
    while((i<65900)&&(i<(len-1)))
    {
        buffer[bo]=payload[i];
        dcs=dcs+buffer[bo];
        bo++;
        i++;
    }
    dcs=(-dcs);
    buffer[bo++]=dcs;
    write(fd,buffer,bo);
    //printf("Sent %d bytes\n",bo);
    //printf("Whole packet: ");
    //i=0;
    //while(i<bo)
    //{
    //  printf("0x%02X ",buffer[i]);
    //  i++;
    //}
    //printf("\n");
}
void sendcmd(char * payload)    //Accepts space separated argument list like "0xFF 0x0A 255 'USERID' 0 0"
{               //strings are quoted in half quotes. half quotes inside a string are escaped \\'
    int i,v;        //full quotes inside a string are escaped like \"
    static unsigned char buffer[1024];  //back slashes inside a string are escaped like \\\\  .
    static int bo;      //(The first escape or escape pair is for the C compiler, the second for this function:
    bo=0;           // The actual contents of the string are just \' and \\)
    i=0;            // Numeric formats supported are hex (0xNN), base ten (123), and octal (0377).
    if(debug){printf("sendcmd: ");}
    while(payload[i])
    {
        if((payload[i]!='\'')&&(payload[i]!=' '))
        {
            v=strtoul(&payload[i],NULL,0);
            buffer[bo++]=v;
            if(debug){printf("0x%02X, ",v);}
            while(payload[i]>' '){i++;}
        }
        else if(payload[i]=='\'')
        {
            i++;
            int keeprun;
            keeprun=1;
            while(keeprun)
            {
                if(payload[i]=='\\')
                {
                    i++;
                }else{
                    if(payload[i]=='\''){keeprun=0;}
                }

                if((keeprun)&&(payload[i]))
                {
                    buffer[bo++]=payload[i];
                    if(debug){printf("%c",payload[i]);}

                }
                i++;
            }
            if(debug){printf(", ");}

        }
        else
        {
            i++;
        }
    }
    if(debug){printf("\n");}
    sendpacket(buffer,bo);
}
 类似资料:
  • 我正在尝试使用nfc android库读取ISO15693 RFID标签: 有关该标签的更多信息如下:http://img42.com/gw07d+

  • 我开发了一个系统,可以使用带有PN532芯片的阅读器读取NFC标签。它工作正常。我可以阅读米费尔经典和米费尔超轻标签。 现在我想使用带有Android 4.4.2的Nexus平板电脑来模拟标签。我没有Android开发经验,但我认为这是可能的。 我已经在Nexus平板电脑中设置了NFC通信,但我想我必须下载或编写一些应用程序来模拟Tag和NDEF通信。 最简单的方法是什么?

  • 我有一台LG D320nAndroid手机,elechouse的PN532 nfc模块和斯托尔曼的NFCPlayer,我可以用它正确阅读NFC标签。 我在这里测试了一个样本:https://github.com/grundid/host-card-emulation-sample 当我把一台Android设备读作标签,另一台Android设备读作阅读器时,它工作得很好。但我无法通过NFCPlaye

  • 我正在开发一个用于从MIFARE标签读取和写入数据的应用程序。我买了一个可以使用NFC技术读取和写入MIFARE标签操作的设备。 NFC屏蔽 我一直在使用MIFARE ultralight标签,但在尝试验证特定内存地址时遇到了问题。由于这个原因,我不能开始阅读。这是我的Arduino代码: 此读取代码是为Arduino Mega 2560和Seeedstudio NFC Shield v1.0和M

  • 我是Arduino的新手。我正在尝试将 ID 写入我的 NFC 卡。我使用了示例中的 PN532 库和代码。我不能比更进一步。还有哪个块正在尝试进行身份验证?我在输出中看不到它。 输出: 找到1个标签 传感器响应:0x44 Sel响应:0x0 0x4 0xB9 0xC9 0xBA 0x20 0x4B0x80 读卡片#3122678656 代码是:

  • 更新:从本文NFC论坛类型标签中,您可以发现Mifare Ultralight与NDEF兼容。Android设备可以轻松读取这种类型的标签。