2013-04-26 2 views
2

필자는 원격 측정 스트림을 가지고 있으며이 측정 스트림은 CRC를 각 원격 측정 프레임의 끝에 추가하는 하드웨어 CRC 생성기를 통과합니다. 이제 하드웨어에서 생성 된 CRC를 확인하기 위해 무언가를 만들려고합니다. 올바른 CRC (여러 번 검증 됨)를 계산하는 오래된 레거시 코드 (아래 참조)가 있습니다. 그러나 각 원격 측정 프레임이 300 바이트 이상이고 처리 할 수있는 프레임이 10,000,000 개 이상일 수 있으므로 속도가 느립니다.어떤 CRC Alogrithim입니까? 개선하는 방법?

일부 연구를 통해 나는 표적 접근 방식을 가리키는 몇 가지 문헌을 발견했습니다. 레거시 방법은 Poly of 0x8005를 사용하고 처리하기 전에 각 바이트의 비트 순서를 반대로하고 CRC를 0으로 초기화합니다. 그러나 역전 된 입력과 반대가 아닌 입력을 가진 폴리를위한 테이블을 만들고 단지 첫 번째 바이트의 데이터 (0x10)를 처리하려고하면 레거시 방식이 생성하는 것과 일치하는 것을 얻을 수 없습니다.

calcCRC16 함수 (아래)에서 기존 메서드는 다른 사람이 MSB를 확인하는 것처럼 보이는 LSB를 확인합니다 ... 그리고 내가 본 다른 예제가있는 곳으로 비트 시프트가 있습니다. 왜 비트 순서가이 함수에 전달되기 전에 바뀌 었는지 알기가 어렵습니다. 나는 온라인 계산기를 & 수동으로 8005에서 A001 (역전 된), 정상 및 역 입력 된 바이트, 그리고 내가 생각할 수있는 모든 조합으로 전환하는 테이블에서 조회를하고 있지만 어떤 테이블 접근 방식과도 일치하지는 않는다. 하드웨어 구현시 올바른 것으로 알고있는 레거시 코드

내가 분명한 뭔가를 놓치면 누구든지 나를 도울 수 있습니까? 동일한 출력을 만들기 위해 테이블 ​​기반 접근 방식을 만드는 방법에 대해 어떻게 생각하십니까? 저는 C++의 초심자이며 CRC 생성에 익숙하지 않아 뭔가 근본적인 것을 간과 할 수 있습니다. 하드웨어 CRC에 대해 검증 된 샘플 코드와 출력은 다음과 같습니다

샘플 코드 :
: 난 그냥 열심히 예를 들어

/** ******************************************************************************** 
* TEST CRC METHOD 
*******************************************************************************/ 
#include <iostream> 

using namespace std; 

unsigned char swapBits(unsigned char d); 
void calcCRC16(unsigned int *CRCVal, unsigned char value); 

/** ************************************************************************** 
* @function main 
* TEST CRC METHOd 
*******************************************************************************/ 
int main(int argc, char* argv[]) 
{ 
    short   dataLength = 5; 
    unsigned int givenCrc; 
    unsigned int calcCrc;  
    unsigned char byte[] = {0x10,0xbb,0x42,0x4d,0xfd}; 

    /* Init CRC. */ 
    calcCrc = 0; 
    cout << "Inital CRC = " << hex << calcCrc << "\n"; 
    /* Read frame data. */ 
    for (int i = 0; i < dataLength; i++) 
    { 
     cout << "byte = " << hex << static_cast<int16_t>(byte[i]) << " "; 
     calcCRC16(&calcCrc, swapBits(byte[i])); 
     cout << "calcCRC = " << hex << calcCrc << "\n"; 
    } 
} 

/** ******************************************************************** 
* @function swapBits 
* Swaps the bits so they match the order sent to CRC Gen Hardware 
************************************************************************/ 
unsigned char swapBits(unsigned char d) 
{ 
    unsigned char t = 0; 
    int i   = 0; 
    int n   = 0x80; 

    for(i=0x01; i<0x100; i=i<<1) 
    { 
     if (d & i) 
     { 
      t|=n; 
     } 
     n=n>>1; 
    } 
    return t; 
} 

/** ******************************************************************** 
* @function calcCRC16 
* WORKING METHOD VERIFIED AGAINST CRC HARDWARE 
************************************************************************/ 
void calcCRC16(unsigned int *CRCVal, unsigned char value) 
{ 
    unsigned char lsb; 
    unsigned char bcnt; 

    for (bcnt=0 ; bcnt<8 ; bcnt++) 
    { 
     lsb = (value^*CRCVal) & 0x01; 
     *CRCVal >>= 1; 
     value >>= 1; 
     if (lsb != 0) 
     { 
      *CRCVal ^= 0x8005; 
     } 
    } 
} 

출력으로 알고 원격 측정 스트림에서 몇 바이트 코드 Inital CRC = 0
바이트 = 10 calcCRC = b804
바이트 = BB calcCRC = 1fb8
바이트 = 42 = calcCRC 461d
012,351,바이트 = 4D calcCRC = 3d47
바이트 = FD calcCRC = 683e

답변

3

rev16(crc16(0, buf, len)) 당신에게 나와의 CRC를 줄 것이다.

#include <stdio.h> 

static unsigned short crc16_table[] = { 
    0x0000, 0xa001, 0xe003, 0x4002, 0x6007, 0xc006, 0x8004, 0x2005, 
    0xc00e, 0x600f, 0x200d, 0x800c, 0xa009, 0x0008, 0x400a, 0xe00b, 
    0x201d, 0x801c, 0xc01e, 0x601f, 0x401a, 0xe01b, 0xa019, 0x0018, 
    0xe013, 0x4012, 0x0010, 0xa011, 0x8014, 0x2015, 0x6017, 0xc016, 
    0x403a, 0xe03b, 0xa039, 0x0038, 0x203d, 0x803c, 0xc03e, 0x603f, 
    0x8034, 0x2035, 0x6037, 0xc036, 0xe033, 0x4032, 0x0030, 0xa031, 
    0x6027, 0xc026, 0x8024, 0x2025, 0x0020, 0xa021, 0xe023, 0x4022, 
    0xa029, 0x0028, 0x402a, 0xe02b, 0xc02e, 0x602f, 0x202d, 0x802c, 
    0x8074, 0x2075, 0x6077, 0xc076, 0xe073, 0x4072, 0x0070, 0xa071, 
    0x407a, 0xe07b, 0xa079, 0x0078, 0x207d, 0x807c, 0xc07e, 0x607f, 
    0xa069, 0x0068, 0x406a, 0xe06b, 0xc06e, 0x606f, 0x206d, 0x806c, 
    0x6067, 0xc066, 0x8064, 0x2065, 0x0060, 0xa061, 0xe063, 0x4062, 
    0xc04e, 0x604f, 0x204d, 0x804c, 0xa049, 0x0048, 0x404a, 0xe04b, 
    0x0040, 0xa041, 0xe043, 0x4042, 0x6047, 0xc046, 0x8044, 0x2045, 
    0xe053, 0x4052, 0x0050, 0xa051, 0x8054, 0x2055, 0x6057, 0xc056, 
    0x205d, 0x805c, 0xc05e, 0x605f, 0x405a, 0xe05b, 0xa059, 0x0058, 
    0xa0e9, 0x00e8, 0x40ea, 0xe0eb, 0xc0ee, 0x60ef, 0x20ed, 0x80ec, 
    0x60e7, 0xc0e6, 0x80e4, 0x20e5, 0x00e0, 0xa0e1, 0xe0e3, 0x40e2, 
    0x80f4, 0x20f5, 0x60f7, 0xc0f6, 0xe0f3, 0x40f2, 0x00f0, 0xa0f1, 
    0x40fa, 0xe0fb, 0xa0f9, 0x00f8, 0x20fd, 0x80fc, 0xc0fe, 0x60ff, 
    0xe0d3, 0x40d2, 0x00d0, 0xa0d1, 0x80d4, 0x20d5, 0x60d7, 0xc0d6, 
    0x20dd, 0x80dc, 0xc0de, 0x60df, 0x40da, 0xe0db, 0xa0d9, 0x00d8, 
    0xc0ce, 0x60cf, 0x20cd, 0x80cc, 0xa0c9, 0x00c8, 0x40ca, 0xe0cb, 
    0x00c0, 0xa0c1, 0xe0c3, 0x40c2, 0x60c7, 0xc0c6, 0x80c4, 0x20c5, 
    0x209d, 0x809c, 0xc09e, 0x609f, 0x409a, 0xe09b, 0xa099, 0x0098, 
    0xe093, 0x4092, 0x0090, 0xa091, 0x8094, 0x2095, 0x6097, 0xc096, 
    0x0080, 0xa081, 0xe083, 0x4082, 0x6087, 0xc086, 0x8084, 0x2085, 
    0xc08e, 0x608f, 0x208d, 0x808c, 0xa089, 0x0088, 0x408a, 0xe08b, 
    0x60a7, 0xc0a6, 0x80a4, 0x20a5, 0x00a0, 0xa0a1, 0xe0a3, 0x40a2, 
    0xa0a9, 0x00a8, 0x40aa, 0xe0ab, 0xc0ae, 0x60af, 0x20ad, 0x80ac, 
    0x40ba, 0xe0bb, 0xa0b9, 0x00b8, 0x20bd, 0x80bc, 0xc0be, 0x60bf, 
    0x80b4, 0x20b5, 0x60b7, 0xc0b6, 0xe0b3, 0x40b2, 0x00b0, 0xa0b1}; 

static unsigned char rev_table[] = { 
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 
    0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 
    0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 
    0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 
    0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 
    0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 
    0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 
    0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 
    0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 
    0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 
    0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 
    0x3f, 0xbf, 0x7f, 0xff}; 

unsigned crc16(unsigned crc, unsigned char *buf, int len) 
{ 
    while (len--) { 
     crc ^= *buf++ << 8; 
     crc = (crc << 8)^crc16_table[(crc >> 8) & 0xff]; 
    } 
    return crc & 0xffff; 
} 

inline unsigned rev16(unsigned val) 
{ 
    return (rev_table[val & 0xff] << 8) | rev_table[(val >> 8) & 0xff]; 
} 
+0

멋진 작품 마크 – TonyK

+0

감사합니다! 나는 어느 시점에서 A001 테이블을 시도했지만 CRC의 최종 16 비트 반전으로 인해 버려졌습니다. 참고로, 작은 샘플 원격 측정 파일에서 처리 시간이 1 분에서 1.5 초로 단축되었습니다. 다시 한번 감사드립니다. –