啊行..想這似乎在沒有成功的數據表的相關指示一切後,我轉身業餘無線電到13.56MHz的CW/LSB和有沒有什麼可以聽到的。所以只是爲了踢我嘗試了RFRegulationTest命令,並解鎖了整個事情!似乎是一個測試命令,打開發射機並保持打開狀態,直到發出另一個命令爲止......但它會根據需要初始化某些東西!
所以這裏需要做的卡NXP NP532掃描命令: (我使用RS232在115200,但應該是其他接口類似。)
你發送給它:
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0xFF 0x03 0xFD 0xD4 0x58 0x00 0xD4
,你會得到一個ACK和發射器將在鍵: 爲0x00爲0x00 0xFF的爲0x00 0xFF的0×00
而在這一點上,發射器將鍵上。也許讓它做超過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 0×02 0×00命令時,通過嘗試次數設定爲小於0xFF的一個數字,這樣它會嘗試:
sendcmd("0x32 0x05 0xFF 0x01 0x10")
在這種情況下,當你給讀命令(0x4A 0×02×00),它會嘗試第二(0×10次)的一小部分,然後放棄,併發送包含包:
0x4B, 0x00
這意味着「牌發現:零。 「
有關詳細信息,請參閱數據表,它告訴您需要了解的所有信息,除非我運行射頻測試命令之前,無法知道如何啓用發射器。
無論如何,如果你喜歡,只要持續發送第二個命令幾次或更慢,並且每次發送該命令時,它都會掃描並讓你知道是否有範圍內的卡!
或者,如果您將重試次數設置爲0xFF,則它會一直嘗試,直到它檢測到一張卡,然後您只需在發現卡時重新發送scan-for-card命令。
0xFF的長字符串只是爲了喚醒設備,因爲它進入睡眠狀態,並且會丟失發送的前幾個字節。
我給出的以一串0xFF開頭的例子是整個完整的數據包,包括前導碼,長度字段,校驗和和計算的所有數據。您可以直接發送它們來掃描卡片。
初始RF測試命令和重試設置命令只需要在上電時運行一次,之後只需根據需要重新發送讀取命令。
我PN532芯片報告本身作爲版本:1.6
這裏是我的小樣本程序:
(我從SO後解禁的RS232初始化部分 - 感謝誰寫的!)
(它適用於Linux。編譯gcc nfc.c -o nfc.e)
(應該能夠將它移植到任何平臺上,你只需要處理串口 - 其餘與平臺無關)
(也請注意,這僅僅是掃描卡片並返回序列號/ NFCID,並且僅適用於Mifare,ISO/IEC14443-3 A型卡在106kbps的被動模式下。如果你想實際讀/寫卡上的內存,你必須編寫更多的代碼,但這至少說明了開始以及命令結構的工作方式,並提供了一些方便的例程來發送和解碼數據包。)
#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);
}