crc 16 소스 코드 입니다.
1. CRC-16 다항식 을 선택 합니다.
// 0x8005 for CRC16-IBM, == x16 + x15 + x2 + x0 == 1 1000 0000 0000 0101
// 0x1021 for CRC16-CCITT == x16 + x12 + x5 + x0 == 1 0001 0000 0010 0001
#define POLYNOMIAL 0x8005
#define TABLE_SIZE 256
2. table 방식과 직접 계산 방식을 하였는데, 테이블은 256 개로 합니다.
// CRC-16 lookup 테이블
uint16_t crc16_table[TABLE_SIZE];
// CRC-16 테이블 생성 함수
void generate_crc16_table(void) {
int i,j;
uint16_t crc;
for (i = 0; i < TABLE_SIZE; i++) {
crc = i << 8; // 상위 8비트를 i로 설정
for (j = 0; j < 8; j++) {
if (crc & 0x8000) { // 최상위 비트가 1이면
crc = (crc << 1) ^ POLYNOMIAL; // 왼쪽 시프트 후 다항식과 XOR
} else {
crc <<= 1; // 왼쪽 시프트
}
}
crc16_table[i] = crc;
}
}
3. table 이용 하여 crc16 계산
uint16_t crc16_useTable(unsigned char* pD, uint16_t len) {
uint16_t i, j;
uint16_t crc_accum = 0;
for (j = 0; j < len; j++)
{
i = ((uint16_t)(crc_accum >> 8) ^ pD[j]) & 0xFF;
crc_accum = (crc_accum << 8) ^ crc16_table[i];
}
return crc_accum;
}
4. 직접 crc 계산
uint16_t crc16_Direct(const uint8_t* data, int length) {
uint16_t crc = 0x0000;
while (length--) {
crc ^= (*data++) << 8;
for (int i = 0; i < 8; ++i) {
if (crc & 0x8000)
crc = (crc << 1) ^ POLYNOMIAL;
else
crc <<= 1;
}
}
return crc;
}
5. 결과 보기
int _tmain(int argc, _TCHAR* argv[])
{
uint8_t d[] = { 0x41, 0x42, 0x43, 0x44 }; // data = ABCD
int i;
generate_crc16_table(); // make table
print_crc16_table(); // show table
printf(" Data:"); for(i=0; i<sizeof(d); i++ ) printf(" 0x%02X", d[i]); // show input data
printf(" >>>Table: 0x%04X, ", crc16_useTable(d, sizeof(d))); // result
printf(" >>>Direct: 0x%04X\n", crc16_Direct(d, sizeof(d))); // result
return 0;
}
여기서는 간단히 결과만 보는 코드 인데, 첨부 소스는 변환하는데 걸리는 시간 계산 하기 위하여 조금 바꾸 었읍니다.
Look Up Table 쓰는 방식이, 직접 계산 하는 방식 보다 반도 안걸리 네요.
6. crc16-ibm table
Polynomial = 0x8005, crc16-ibm table
uint16_t crc16_table[256] = {
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
};
7. crc16-ccitt table
Polynomial = 0x1021, crc16-ccitt table
uint16_t crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
8. CRC16-CCITT 로 문자 A ( 0x41) 때와 ABCD 때 CRC 구하기
보낼 데이터 : 0x41 의 CRC 직접 구해 보기
0x41 뒤에 16 bit 0 추가
= 0x41 00 00
= 0100 0001 0000 0000 0000 0000 을
crc16 ccitt 0x1021
= 1 0001 0000 0010 0001 로 나눈다
______________________________
| 0100 0001 0000 0000 0000 0000
100 0100 0000 1000 01
----------------------------
101 0000 1000 0100 000
100 0100 0000 1000 010
----------------------
1 0100 1000 1100 0100
1 0001 0000 0010 0001
---------------------
0101 1000 1110 0101 == 0x58E5 <= CRC
마찬가지로 보낼 데이타가 ABCD 이면
0x41424344 뒤에 16 bit 0 추가
= 0x41 42 43 44 00 00
= 0100 0001 0100 0010 0100 0011 0100 0100 0000 0000 0000 0000 을
crc16 ccitt 0x1021
= 1 0001 0000 0010 0001 로 나눈다
CRC 는 0x3B3A 로 나온다.
9. 전체 소스
수고 하셨읍니다.
'개발 > 통신' 카테고리의 다른 글
| 코텀 CoTerm: Serial RS232, TCP, UDP 통신 Terminal 프로그램 (4) | 2024.11.13 |
|---|---|
| DVR 한화비전 (0) | 2024.02.18 |
| CH9121 시리얼(ttl) 이더넷 모듈 (CH9121 Serial Ethernet Module) (0) | 2023.10.30 |
| SERIAL com(rs232) port PLOT chart 화면에 그림 그리기 모음 (0) | 2023.04.04 |
| serial(rs232, rs485), LAN(tcp, udp)통신 Terminal 모음 (0) | 2023.01.09 |