RFID 분석

2013.10.01 _ RFID _ Host Commands _ [Inventory]

성엽이 2013. 10. 1. 10:01

   RFID (Radio Frequency Identification : 무선 식별자)  


개요 

ISO15693 규약에 따른 Host Commands 를 이용해서 칩과 근거리 무선통신이 가능하다. ( 리더기 - 칩 )

안테나에서 전자파가 발생해 칩에 전원을 인가하여 칩이 부팅되서 간단한 통신이 가능하다. 


 Source

#include <stdio.h>

#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/signal.h>

#define  CRC_POLYNOM  0x8408
#define  CRC_PRESET  0xFFFF


#define  SPEED  B38400
#define  SPORT  "/dev/ttyS0"

unsigned short CRC16( unsigned char *DATA , unsigned int cnt );
volatile  int  iBreak=0;
void Handle_Serial_Sig(int );

int main()
{
  char cBuff[255];  // 수신용 버퍼
  int iDev = 0;    // 장치 데스크립션 
  int iRet = 0;    // 반환값 
  struct termios stOldState;  // 기존 Serial Port 상태 정보 
  struct termios stNewState;  // 새로운 Serial Port 상태 정보 
  struct sigaction stSigAct;  // 시그널 액션 설정 
  int iCnt;
  unsigned char ucTemp;
  //unsigned char ucRecvBuff[255];


  unsigned char ucBuff[255]= {

      /*  0x06, 0x00, 0x52, 0x00,*/ // Baud Rate Detection
    
      /*0x0D, 

        0x00,

        0x71,

        0x00,

        0x30,  // OS : Beep Mode FLASH

        0x00,  
        0x00,  // OSF : Frequency
        0x00,  
        0x0A,  // OST 1000ms = 1초
        0x00,
        0x00,*/
  // Set ouput Test ( Beep )
        
        /*0x05,
        0x00,
        0x65,
        0xFF,
        0xFF*/ 
// Get Software Version

        0x07,
        0x00,
        0xB0,
        0x01,
        0x00,
        0xFF,
        0xFF   // Host Commands
        };

  
  iDev = open(SPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);

  if0 > iDev )  // 시리얼 포트 Open Error
  {
    perror(SPORT);
    exit(-100);
  }
  
  // 시리얼 포트 설정 전에 시그널 핸들러 등록 
  bzero(&stSigAct, sizeof(stSigAct));

  stSigAct.sa_handler = Handle_Serial_Sig;
  sigaction(SIGIO, &stSigAct, NULL);

  // SIGIO signal을 수신하도록 설정
  fcntl(iDev, F_SETOWN, getpid());

  // file descriptor를 비동기로 설정
  fcntl(iDev, F_SETFL, FASYNC);

  tcgetattr(iDev, &stOldState);  // 현재 Serial Port 상태 저장 
  bzero(&stNewState, sizeof(stNewState));  // 구조체 초기화

  stNewState.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD | PARENB;

  stNewState.c_iflag = IGNPAR | ICRNL;
  stNewState.c_oflag = 0;      // 수신된 데이터를 그대로 출력 
//  stNewState.c_lflag = ICANON;  // read시 리턴되기 위한 최소 문자 개수 지정 
                
  stNewState.c_lflag = 0;      // Data 를 받기 위해서는 Non-Canonical 을 사용 하겠다.
                  // 
  stNewState.c_cc[VMIN] = 1;
  stNewState.c_cc[VTIME] = 0;

  // 시리얼 포트 수신 큐 초기화 
  tcflush(iDev, TCIFLUSH);
  
  // 시리얼 포트에 새 속성 적용
  tcsetattr(iDev, TCSANOW, &stNewState);

  // CRC16 호출
  *((unsigned short *)(&ucBuff[ucBuff[0]-2]))=CRC16(ucBuff, ucBuff[0]-2);

  for(iCnt=0; iCnt < ucBuff[0] ; iCnt++)
  {  
    printf("%02X\n",ucBuff[iCnt]);
  }  
  
  // ucBuff[0] => 길이 
  write(iDev, ucBuff, ucBuff[0]);
  read(iDev, ucBuff, sizeof(ucBuff));
  
  // 길이가 11이 나와서 13으로 다시 넣음
  //ucBuff[0] = 13;
  
  printf("<Recv>\n");
  
  for(iCnt=0 ; iCnt < ucBuff[0]; ++iCnt)
  {
    printf("%02X ", ucBuff[iCnt]);
  }

  putchar('\n');
  
  // 길이가 11개가 나와서 테스트 
  //printf("%04x\n", CRC16(ucBuff, ucBuff[0]-5));  
  //printf("%04x\n", CRC16(ucBuff, ucBuff[0]-2));

  ucTemp = ucBuff[4];
  ucBuff[4= ucBuff[5];
  ucBuff[5= ucTemp;
  
/*  printf("SW-REV  : %d\n", *((unsigned short *)(&ucBuff[4])));
  printf("D-REV   : %d\n", *((unsigned short *)(&ucBuff[6])));
  printf("HW-Type : %d\n", *((unsigned short *)(&ucBuff[7])));
  printf("SW-Type : %d\n", *((unsigned short *)(&ucBuff[8])));

  // 빅인디언이므로 스위칭 시켜서 번호를 맞춰줌
  ucTemp = ucBuff[9];
  ucBuff[9] = ucBuff[10];
  ucBuff[10] = ucTemp;
  
  printf("TR-TYPE : ");  

  if( 0 != ((*((unsigned short *)(&ucBuff[9]))) & 0x0001 ))
  {
    printf("[I-Code 1] ");
  }
  if( 0 != ((*((unsigned short *)(&ucBuff[9]))) & 0x0002 ))
  {
    printf("[Tag-it HF] ");
  }
  if( 0 != ((*((unsigned short *)(&ucBuff[9]))) & 0x0008 ))
  {
    printf("[ISO 15693] ");
  }
  if( 0 != ((*((unsigned short *)(&ucBuff[9]))) & 0x0040 ))
  {
    printf("[I-Code EPC] ");
  }
  if( 0 != ((*((unsigned short *)(&ucBuff[9]))) & 0x0080 ))
  {
    printf("[I-Code UID] ");
  }

  putchar('\n');*/


  printf("DATA SETS  : %d\n", *((unsigned short *)(&ucBuff[4])));

  printf("TR-TYPE : ");  
  
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x80 ))
  {
    printf("[UHF Transponder] ");
  }
  else
  {
    printf("[13.56Mhz Transponder] ");
  }

  putchar('\n');
  
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x00 ))
  {
    printf("[Philips I-Code 1] ");
  }
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x01 ))
  {
    printf("[Texas Instruments Tag-it HF] ");
  }
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x03 ))
  {
    printf("[ISO 15693 Tags] ");
  }
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x06 ))
  {
    printf("[Philips I-Code EPC] ");
  }
  if0 != ((*((unsigned short *)(&ucBuff[5]))) & 0x07 ))
  {
    printf("[Philips I-Code UID] ");
  }

  
  /*while(1)
  {
    if( 1 == iBreak )
    {
      iRet = read(iDev, cBuff, 255);  // 시리얼 포트로부터 데이터 수신
      cBuff[iRet] =0;
      printf("[%s]:[%d]\n", cBuff, iRet);
      break;
    }
    else
    {
      sleep(2);
    }  
    printf("Go Sleep\n");
  }*/

  

  // 시리얼 포트의 원래 속성 복귀
  tcsetattr(iDev, TCSANOW, &stOldState);
  close(iDev);  // 시리얼 포트 닫음 

  return 0;
}

void Handle_Serial_Sig(int Arg)
{
  printf("Receive SIGIO Signal\n");
  iBreak = 1;
}


unsigned short CRC16( unsigned char *DATA , unsigned int cnt )
{
  unsigned short crc = CRC_PRESET;
  int i;
  int j;

  for (i = 0; i < cnt; i++) /* cnt = number of protocol bytes without CRC */
  {
    crc ^= DATA[i];
    for (j = 0; j < 8; j++)
    {
      if (crc & 0x0001)
      {
        crc = (crc >> 1) ^ CRC_POLYNOM;
      }
      else
      {
        crc = (crc >> 1);
      }
    }
  }

  return crc;  
}



설명 및 결과

 



: 기본적으로 RFID 송수신을 할때 DATA Format 을 가진다. 그 틀은 위의 그림과 같다.



: 리더기에서 읽은 카드의 정보(UID)를 응답해준다. MODE 는 Standard

※ 1~3Byte는 데이터길이, 장치번호, 제어바이트 이다. Recv 부분에서 데이터를 확인가능하다.



 

※ 현재 테스트 키트 이므로 테스트만 하고 있음.



20130925_ISO15693-HostCommand.pdf


SL015M-3-User-Manual.pdf