RFID(Reader control/Host Command)
RFID 실습
HOST <- Reader
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 | #include <windows.h> #include <stdio.h> void text_out(unsigned char *); unsigned short Emb_Crc(void *); int main() { unsigned char msg[] = { 0x0D, 0x00, 0x71, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xFF, 0xFF}; HANDLE hComm; DWORD DW_write; DWORD DW_read; DCB sPS; // 씨리얼 포트 상태 저장 COMMTIMEOUTS cTime; volatile unsigned int dly = 0; volatile unsigned int cnt = 0; volatile unsigned int icnt = 0; // 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; } /* * 포트 초기화 * DCB 구조체 사용 * 길이 * 속도 */ 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 + 11)) = Emb_Crc(msg); WriteFile(hComm, msg, sizeof(msg), &DW_write, 0); ReadFile(hComm, msg, 6, &DW_read, 0); for(icnt = 0; icnt < msg[0]; icnt++) { printf("%02X ", msg[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; } void text_out(unsigned char *msg) { int icnt; for(icnt = 1;icnt <= 13 ;icnt++) { printf("%02d ", icnt); if(icnt == 13) { putchar('\n'); for(icnt = 0;icnt < 13;icnt++) { printf("%02X ", *(msg+icnt)); } putchar('\n'); break; } } return ; } | cs |
추가코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | DWORD DW_read; ReadFile(hComm, msg, 6, &DW_read, 0); for(icnt = 0; icnt < msg[0]; icnt++) { printf("%02X ", msg[icnt]); } ㆍ기존 소스에서 위 코드가 추가 되었다. | cs |
ReadFile 함수를 통해 스펙내용과 동일한 값을 출력 할 수 있다.
실행 결과
Get Software Version
코드
unsigned char msg[128] = { 0x05,
0x00,
0x65,
0xFF, 0xFF};
CRC 비트 위치에 Crc 함수 반환값을 넣어준다.
코드
*((unsigned short *)(msg + msg[0] - 2)) = Emb_Crc(msg);
0 |
1 |
2 |
3 |
4 |
0x05 |
|
|
CRC |
CRC |
읽어오는 양은 13이므로 버퍼크기를 늘여준다.
스펙에 나와있는 비트 값들을 출력해 보자.
출력 코드
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 | #include <windows.h> #include <stdio.h> #define I_Code_1 1 #define Tag_it_HF 2 #define ISO_15693 8 #define I_Code_EPC 64 #define I_Code_UID 128 void text_out(unsigned char *); unsigned short Emb_Crc(void *); int main() { unsigned char msg[128] = { 0x05, 0x00, 0x65, 0xFF, 0xFF}; HANDLE hComm; DWORD DW_write; DWORD DW_read; DCB sPS; // 씨리얼 포트 상태 저장 COMMTIMEOUTS cTime; volatile unsigned int dly = 0; volatile unsigned int cnt = 0; volatile unsigned int icnt = 0; // 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; } /* * 포트 초기화 * DCB 구조체 사용 * 길이 * 속도 */ 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); if(msg[3] != 0) { printf("error\n"); CloseHandle(hComm); return 0; } printf("Revision status of the firmware : %02X%02X\n", msg[4], msg[5]); printf("Revision status of the development firmware : %02X\n", msg[6]); printf("HW-Type : %02X\n", msg[7]); printf("SW-TYPE : %02X\n", msg[8]); printf("suppor Transponders : \n"); printf("\t\tI-Code UID : %s\n", (msg[10] & I_Code_UID) ? "yes" : " no"); printf("\t\tI-Code EPC : %s\n", (msg[10] & I_Code_EPC) ? "yes" : " no"); printf("\t\tISO 15693 : %s\n", (msg[10] & ISO_15693) ? "yes" : " no"); printf("\t\tTag-it HF : %s\n", (msg[10] & Tag_it_HF) ? "yes" : " no"); printf("\t\tI-Code 1 : %s\n", (msg[10] & I_Code_1) ? "yes" : " no"); 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; } void text_out(unsigned char *msg) { int icnt; for(icnt = 1;icnt <= 13 ;icnt++) { printf("%02d ", icnt); if(icnt == 13) { putchar('\n'); for(icnt = 0;icnt < 13;icnt++) { printf("%02X ", *(msg+icnt)); } putchar('\n'); break; } } return ; } | cs |
실행 결과
Protocols for ISO15693 Host Commands
[0x22] Lick Multiple Blocks를 사용하면 카드를 사용할 수 없게 됨으로 사용해선 안된다.
[0xB0] Host commands 를 사용해 보자.
1번 bit에는 REQUST-DATA는 2bit 에 CRCrk 2bit가 존재함으로 7이다.
standard : 17
EPC : 16 / 20
UID : 27
[0x0B] Host command
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 | #include <windows.h> #include <stdio.h> 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; // 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; } /* * 포트 초기화 * DCB 구조체 사용 * 길이 * 속도 */ 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("%d\n", msg[0]); printf("%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 |
카드가 있을 때 RESPONSE-DATA
카드가 없을 때 RESPONSE-DATA
[카드가 없을 때 Status 값]
카드의 종류를 식별하고 카드가 있는지를 검사하는 프로그램 코드는 아래와 같다.
Tag Data
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 | #include <windows.h> #include <stdio.h> 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; // 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; } /* * 포트 초기화 * DCB 구조체 사용 * 길이 * 속도 */ 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); switch(msg[0]) { case 17 : printf("RESPONSE-DATA : standard\n"); break; case 16 : printf("RESPONSE-DATA : I-Code EPC\n"); break; case 20 : printf("RESPONSE-DATA : I-Code EPC\n"); break; case 27 : printf("RESPONSE-DATA : I-Code UID\n"); break; default : printf("No such card ! \n"); break; } 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 |
실행 결과
standard를 분석해보자.
RF-TYPE
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 | #include <windows.h> #include <stdio.h> 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; // 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; } /* * 포트 초기화 * DCB 구조체 사용 * 길이 * 속도 */ 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"); break; } printf("RF TYPE : [%s]\n", (msg[5] & 0xC0) ? "UHF Transponder" : "13.56 MHz Transponder"); 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 |
실행 결과
RFID(UID/Write Multiple Blocks/Read Multiple Blocks)[20121016] (0) | 2018.12.10 |
---|---|
RFID 기초/사운드 출력 (0) | 2018.12.07 |
IoT Module 와이솔 LoRa 전용 모듈 [LOM102A] (0) | 2016.09.13 |