RFID(UID/Write Multiple Blocks/Read Multiple Blocks)
NFC
패시브 태그(수동적 태그) : 리더기가 전기를 보내지 않으면 죽어있는 일반카드
액티브 태그 : 밧데리가 들어 있고 전류가 흐르는 태그
NFC(근거리 무선 통신)란?
UID
같은 모양의 카드일지라도 고유 카드넘버가 존재한다.
두가지 카드를 이용하여 카드넘버를 출력하는 프로그램을 제작해 보자.
UID는 스펙에서 다음과 같이 설명되어 있다.
UID는 8 ~ 15번 bit로 8개의 bit가 존재한다.
UID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | #include <windows.h> #include <stdio.h> #define Philips_I_Code_1 0x00 #define Texas_Instruments_Tag_it_HF 0x01 #define ISO15693_Tags 0x03 #define Philips_I_Code_EPC 0x06 #define Philips_I_Code_UID 0x07 unsigned short Emb_Crc(void *); int main() { unsigned char msg[128] = { 0x07, 0x00, 0xB0, 0x01, 0x00,}; HANDLE hComm; DWORD DW_write; DWORD DW_read; DCB sPS; // 씨리얼 포트 상태 저장 COMMTIMEOUTS cTime; unsigned int icnt; // CreateFile = File open 함수와 같다. COM1은 컴포트1이 열린다. hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(INVALID_HANDLE_VALUE == hComm) { printf("Com port open Error !\n"); return 0; } // 버퍼 설정 if( 0 == SetupComm(hComm, 4096, 4096)) { printf("Buffer setting Error !\n"); CloseHandle(hComm); return 0; } if( 0 == PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR)) { printf("Buffer initialization Error !\n"); CloseHandle(hComm); return 0; } sPS.DCBlength = sizeof(sPS); if( 0 == GetCommState(hComm, &sPS)) { printf("Port status read Error !\n"); CloseHandle(hComm); return 0; } sPS.BaudRate = CBR_38400; // 비트,초 sPS.ByteSize = 8; // 데이터 비트 전송 sPS.Parity = EVENPARITY; // 짝수 sPS.StopBits = ONESTOPBIT; // 정지 비트 // 위 세팅값을 핸들에 넣어준다. if( 0 == SetCommState(hComm, &sPS)) { printf("Port status write Error !\n"); CloseHandle(hComm); return 0; } *((unsigned short *)(msg + msg[0] - 2)) = Emb_Crc(msg); WriteFile(hComm, msg, msg[0], &DW_write, 0); ReadFile(hComm, msg, 1, &DW_read, 0); ReadFile(hComm, msg + 1, msg[0] - 1, &DW_read, 0); printf("tag data : "); switch(msg[0]) { case 17 : printf("[standard]\n"); break; case 16 : printf("[I-Code EPC]\n"); break; case 20 : printf("[ I-Code EPC]\n"); break; case 27 : printf("[I-Code UID]\n"); break; default : printf("[No such card ! ]\n"); CloseHandle(hComm); break; } printf("RF TYPE : [%s]\n", (msg[5] & 0xC0) ? "UHF Transponder" : "13.56 MHz Transponder"); printf("VENDOR : "); switch(msg[5]&0x0F) { case Philips_I_Code_1 : printf("[Philips I-Code 1]\n"); break; case Texas_Instruments_Tag_it_HF : printf("[Texas Instruments Tag-it HF]\n"); break; case ISO15693_Tags : printf("[ISO15693 Tags]\n"); break; case Philips_I_Code_EPC : printf("[Philips I-Code EPC]\n"); break; case Philips_I_Code_UID : printf("[Philips I-Code UID]\n"); break; default : printf("[No such card ! ]\n"); CloseHandle(hComm); break; } printf("%02x\n",msg[5]); //< UID >============================================ printf("UID : "); for(icnt = 0 ; icnt < 8 ; icnt++) { printf("%02X ", msg[7+icnt]); } putchar('\n'); printf("Com port open Success !\n"); CloseHandle(hComm); // 터미널은 닫아주어야한다. return 0; } unsigned short Emb_Crc(void *arg) { unsigned short i; unsigned short j; unsigned short cnt; unsigned short crc=0xFFFF; unsigned short temp; unsigned char *buf = arg; cnt = (*buf) - 2; for(i=0 ; i < cnt ; ++i) { crc^= *(buf + i); for(j=0 ; j < 8 ; ++j) { if(0 != (crc&0x0001)) { crc=(crc>>1)^0x8408; } else { crc=(crc>>1); } } } return crc; } | cs |
위 코드에서 UID를 출력하는 코드이다.
1 2 3 4 5 6 7 8 | //< UID >============================================ printf("UID : "); for(icnt = 0 ; icnt < 8 ; icnt++) { printf("%02X ", msg[7+icnt]); } putchar('\n'); | cs |
카드가 없을때의 UID 값
1번 카드의 UID 값
2번 카드의 UID 값
[0x24] Write Multiple Blocks
DB-SIZE는 다음과 같이 스펙에서 4byte로 고정되어 있음을 알 수 있다.
[0x24] Write Multiple Blocks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | #include <windows.h> #include <stdio.h> unsigned short Emb_Crc(void *); int main() { unsigned char msg[128] = { 0x16, 0x00, 0xB0, 0x24, 0x01, // MODE (addressed mode) 0xE0, // UID (6) 0x04, 0x01, 0x00, 0x2E, 0xB3, 0x88, 0x51, 0x0A, // DB-ADR (14) 0x01, // DB-N 0x04, // DB-SIZE 0x12, // DB 0x34, 0x56, 0x78, }; HANDLE hComm; DWORD DW_write; DWORD DW_read; DCB sPS; COMMTIMEOUTS cTime; unsigned int icnt; // CreateFile = File open 함수와 같다. COM1은 컴포트1이 열린다. hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(INVALID_HANDLE_VALUE == hComm) { printf("Com port open Error !\n"); return 0; } // 버퍼 설정 if( 0 == SetupComm(hComm, 4096, 4096)) { printf("Buffer setting Error !\n"); CloseHandle(hComm); return 0; } if( 0 == PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR)) { printf("Buffer initialization Error !\n"); CloseHandle(hComm); return 0; } sPS.DCBlength = sizeof(sPS); if( 0 == GetCommState(hComm, &sPS)) { printf("Port status read Error !\n"); CloseHandle(hComm); return 0; } sPS.BaudRate = CBR_38400; // 비트,초 sPS.ByteSize = 8; // 데이터 비트 전송 sPS.Parity = EVENPARITY; // 짝수 sPS.StopBits = ONESTOPBIT; // 정지 비트 // 위 세팅값을 핸들에 넣어준다. if( 0 == SetCommState(hComm, &sPS)) { printf("Port status write Error !\n"); CloseHandle(hComm); return 0; } *((unsigned short *)(msg + msg[0] - 2)) = Emb_Crc(msg); //< RFID 로 전송 및 수신>========================== WriteFile(hComm, msg, msg[0], &DW_write, 0); ReadFile(hComm, msg, 1, &DW_read, 0); ReadFile(hComm, msg + 1, msg[0] - 1, &DW_read, 0); //================================================= //< UID >============================================ printf("UID : "); for(icnt = 0; icnt < 8; icnt++) { printf("%02X ", msg[5 + icnt]); } putchar('\n'); printf("DB-ADR : %02X \n", msg[13]); printf("DB-N : %02X \n", msg[14]); printf("DB-SIZE: %02X \n", msg[15]); printf("DB : %02X \n", msg[16]); printf("DB-ADR-E : %02X, %02X\n", msg[4], msg[5]); printf("STATUS : %02X \n", msg[3]); printf("Com port open Success !\n"); CloseHandle(hComm); // 터미널은 닫아주어야한다. return 0; } unsigned short Emb_Crc(void *arg) { unsigned short i; unsigned short j; unsigned short cnt; unsigned short crc=0xFFFF; unsigned short temp; unsigned char *buf = arg; cnt = (*buf) - 2; for(i=0 ; i < cnt ; ++i) { crc^= *(buf + i); for(j=0 ; j < 8 ; ++j) { if(0 != (crc&0x0001)) { crc=(crc>>1)^0x8408; } else { crc=(crc>>1); } } } return crc; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | unsigned char msg[128] = { 0x16, 0x00, 0xB0, 0x24, 0x01, // MODE (addressed mode) 0xE0, // UID (6) 0x04, 0x01, 0x00, 0x2E, 0xB3, 0x88, 0x51, 0x0A, // DB-ADR (14) 0x01, // DB-N 0x04, // DB-SIZE 0x12, // DB 0x34, 0x56, 0x78, }; | cs |
결과는 4번 STATUS를 확인하고 0이 나오면 정상 작동이다.
실행 결과
[0x23] Read Multiple Blocks
[0x23] Read Multiple Blocks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #include <windows.h> #include <stdio.h> unsigned short Emb_Crc(void *); int main() { unsigned char msg[128] = { 0x11, // n 0x00, 0xB0, 0x23, 0x01, // MODE (addressed mode) 0xE0, // UID (6) 0x04, 0x01, 0x00, 0x2E, 0xB3, 0x88, 0x51, 0x0A, // DB-ADR (14) 0x01, // DB-N }; HANDLE hComm; DWORD DW_write; DWORD DW_read; DCB sPS; COMMTIMEOUTS cTime; unsigned int icnt; // CreateFile = File open 함수와 같다. COM1은 컴포트1이 열린다. hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(INVALID_HANDLE_VALUE == hComm) { printf("Com port open Error !\n"); return 0; } // 버퍼 설정 if( 0 == SetupComm(hComm, 4096, 4096)) { printf("Buffer setting Error !\n"); CloseHandle(hComm); return 0; } if( 0 == PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR)) { printf("Buffer initialization Error !\n"); CloseHandle(hComm); return 0; } sPS.DCBlength = sizeof(sPS); if( 0 == GetCommState(hComm, &sPS)) { printf("Port status read Error !\n"); CloseHandle(hComm); return 0; } sPS.BaudRate = CBR_38400; // 비트,초 sPS.ByteSize = 8; // 데이터 비트 전송 sPS.Parity = EVENPARITY; // 짝수 sPS.StopBits = ONESTOPBIT; // 정지 비트 // 위 세팅값을 핸들에 넣어준다. if( 0 == SetCommState(hComm, &sPS)) { printf("Port status write Error !\n"); CloseHandle(hComm); return 0; } *((unsigned short *)(msg + msg[0] - 2)) = Emb_Crc(msg); //< RFID 로 전송 및 수신>========================== WriteFile(hComm, msg, msg[0], &DW_write, 0); ReadFile(hComm, msg, 1, &DW_read, 0); ReadFile(hComm, msg + 1, msg[0] - 1, &DW_read, 0); //================================================= //< UID >============================================ printf("UID : "); for(icnt = 0; icnt < 8; icnt++) { printf("%02X ", msg[5 + icnt]); } putchar('\n'); printf("DB-ADR : %02X \n", msg[13]); printf("DB-N : %02X\n", msg[4]); printf("DB-Size :%02X\n", msg[5]); printf("STATUS : %02X \n", msg[3]); printf("Com port open Success !\n"); CloseHandle(hComm); // 터미널은 닫아주어야한다. return 0; } unsigned short Emb_Crc(void *arg) { unsigned short i; unsigned short j; unsigned short cnt; unsigned short crc=0xFFFF; unsigned short temp; unsigned char *buf = arg; cnt = (*buf) - 2; for(i=0 ; i < cnt ; ++i) { crc^= *(buf + i); for(j=0 ; j < 8 ; ++j) { if(0 != (crc&0x0001)) { crc=(crc>>1)^0x8408; } else { crc=(crc>>1); } } } return crc; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | unsigned char msg[128] = { 0x11, // n 0x00, 0xB0, 0x23, 0x01, // MODE (addressed mode) 0xE0, // UID (6) 0x04, 0x01, 0x00, 0x2E, 0xB3, 0x88, 0x51, 0x0A, // DB-ADR (14) 0x01, // DB-N }; | cs |
실행 결과
앞의 예제에서 카드에 써놓은 123456을 0A 번지에서 읽어 왔다.
RFID(Reader control/Host Command)[20121011] (0) | 2018.12.10 |
---|---|
RFID 기초/사운드 출력 (0) | 2018.12.07 |
IoT Module 와이솔 LoRa 전용 모듈 [LOM102A] (0) | 2016.09.13 |