知道那个是对的方法是这样的,例如CRC函数是CRCCal(PWordArray buf,len);
那么CRC的一个特点就是校验的时候应该是全零,就是说
Var 
Buf:array[0..20] of Word;
X = CRCCal(@Buf,10);
Buf[10] = X;
X = CRCCal(@Buf,11);
X将会是零
你多试几种数据都对的才是对的。
上面的程序我没有时间仔细看,我觉得他们可能对'abc'的理解不同,一个字符a是8位的但是CRC16运算的时候是以16位作运算的所以可以认为ab是一个16位的数也可以认为a的高位全都是零
还有就是我认为你的第二个程序的码表不对,你可以对比一下第一个程序的码表生成的码表和第二个是不是一样,我可以给你一个多项式是X16+x12+x5+1的码表
你参考一下巴:)unsigned short CRC_16[256] = 
{ 0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF,0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C,0xDBE5,0xE97E
           ,0xF8F7,0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E,0x9CC9,0x8D40,0xBFDB,0xAE52,0xDAED,0xCB64
           ,0xF9FF,0xE876,0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434,0x55BD,0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E
           ,0xFAE7,0xC87C,0xD9F5,0x3183,0x200A,0x1291,0x0318,0x77A7,0x662E,0x54B5,0x453C,0xBDCB,0xAC42,0x9ED9,0x8F50
           ,0xFBEF,0xEA66,0xD8FD,0xC974,0x4204,0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB,0xCE4C,0xDFC5,0xED5E
           ,0xFCD7,0x8868,0x99E1,0xAB7A,0xBAF3,0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A,0xDECD,0xCF44
           ,0xFDDF,0xEC56,0x98E9,0x8960,0xBBFB,0xAA72,0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9,0xEF4E
           ,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1,0x7387,0x620E,0x5095,0x411C,0x35A3,0x242A,0x16B1,0x0738
           ,0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70,0x8408,0x9581,0xA71A,0xB693,0xC22C,0xD3A5,0xE13E
           ,0xF0B7,0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76,0x7CFF,0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324
           ,0xF1BF,0xE036,0x18C1,0x0948,0x3BD3,0x2A5A,0x5EE5,0x4F6C,0x7DF7,0x6C7E,0xA50A,0xB483,0x8618,0x9791,0xE32E
           ,0xF2A7,0xC03C,0xD1B5,0x2942,0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD,0xB58B,0xA402,0x9699,0x8710
           ,0xF3AF,0xE226,0xD0BD,0xC134,0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C,0xC60C,0xD785,0xE51E
           ,0xF497,0x8028,0x91A1,0xA33A,0xB2B3,0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB,0xD68D,0xC704
           ,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232,0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1,0x0D68,0x3FF3,0x2E7A,0xE70E
           ,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1,0x6B46,0x7ACF,0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9
           ,0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9,0x8330,0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1
           ,0x0F78  };

解决方案 »

  1.   

    知其然还要知其所以然嘛,我写过一点东东,供参考,来自我和太可怕的主页:
    http://mental.top263.net/mentals/progart/tech/crc16_32.htmCRC-16/CRC-32 程序代码   
         不久前写一程序时要用到 CRC-16 ,但找来找去只在 UDDF 里找到一个 Delphi 的 CRC-32 程序代码,而且是用查表法,虽然说查表法速度快,但 256 项 32 位数据我怀疑可能会有输入错误, 让人不是那么放心,而我又不知道这个表是怎么算出来的。后来我又在一本两年前的笔记本里找到一段关于 CRC 的内容, 也不知是从哪里抄来的,还好里面有一段程序代码,是 CRC-16 的,这段程序正是产生 CRC 表的, 可是这区区几行的程序(基本上与下面的 BuilderTable16 函数相同)看得我一头雾水,直到这两天才弄明白, 并据此推出 CRC-32 的算法,现将全部程序列在下面,并作一些说明以助于理解,不但要知其然,还要知其所以然嘛:     // 注意:因最高位一定为“1”,故略去
    const unsigned short cnCRC_16    = 0x8005;
        // CRC-16    = X16 + X15 + X2 + X0
    const unsigned short cnCRC_CCITT = 0x1021;
        // CRC-CCITT = X16 + X12 + X5 + X0,据说这个 16 位 CRC 多项式比上一个要好
    const unsigned long  cnCRC_32    = 0x04C10DB7;
        // CRC-32    = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + X0unsigned long Table_CRC[256]; // CRC 表//  构造 16 位 CRC 表
    void BuildTable16( unsigned short aPoly )
    {
        unsigned short i, j;
        unsigned short nData;
        unsigned short nAccum;    for ( i = 0; i < 256; i++ )
        {
            nData = ( unsigned short )( i << 8 );
            nAccum = 0;
            for ( j = 0; j < 8; j++ )
            {
                if ( ( nData ^ nAccum ) & 0x8000 )
                    nAccum = ( nAccum << 1 ) ^ aPoly;
                else
                    nAccum <<= 1;
                nData <<= 1;
            }
            Table_CRC[i] = ( unsigned long )nAccum;
        }
    }//  计算 16 位 CRC 值,CRC-16 或 CRC-CCITT
    unsigned short CRC_16( unsigned char * aData, unsigned long aSize )
    {
        unsigned long  i;
        unsigned short nAccum = 0;    BuildTable16( cnCRC_16 ); //  or cnCRC_CCITT
        for ( i = 0; i < aSize; i++ )
            nAccum = ( nAccum << 8 ) ^ ( unsigned short )Table_CRC[( nAccum >> 8 ) ^ *aData++];
        return nAccum;
    }//  构造 32 位 CRC 表
    void BuildTable32( unsigned long aPoly )
    {
        unsigned long i, j;
        unsigned long nData;
        unsigned long nAccum;    for ( i = 0; i < 256; i++ )
        {
            nData = ( unsigned long )( i << 24 );
            nAccum = 0;
            for ( j = 0; j < 8; j++ )
            {
                if ( ( nData ^ nAccum ) & 0x80000000 )
                    nAccum = ( nAccum << 1 ) ^ aPoly;
                else
                    nAccum <<= 1;
                nData <<= 1;
            }
            Table_CRC[i] = nAccum;
        }
    }//  计算 32 位 CRC-32 值
    unsigned long CRC_32( unsigned char * aData, unsigned long aSize )
    {
        unsigned long i;
        unsigned long nAccum = 0;    BuildTable32( cnCRC_32 );
        for ( i = 0; i < aSize; i++ )
            nAccum = ( nAccum << 8 ) ^ Table_CRC[( nAccum >> 24 ) ^ *aData++];
        return nAccum;
    }说明: CRC 的计算原理如下(一个字节的简单例子)
        11011000 00000000 00000000  <- 一个字节数据, 左移 16b
       ^10001000 00010000 1         <- CRC-CCITT 多项式, 17b
        --------------------------
         1010000 00010000 10        <- 中间余数
        ^1000100 00001000 01
         -------------------------
           10100 00011000 1100
          ^10001 00000010 0001
           -----------------------
             101 00011010 110100
            ^100 01000000 100001
             ---------------------
               1 01011010 01010100
              ^1 00010000 00100001
               -------------------
                 01001010 01110101  <- 16b CRC仿此,可推出两个字节数据计算如下:d 为数据,p 为项式,a 为余数
        dddddddd dddddddd 00000000 00000000 <- 数据 D ( D1, D0, 0, 0 )
       ^pppppppp pppppppp p                 <- 多项式 P
        -----------------------------------
        ...
                 aaaaaaaa aaaaaaaa 0        <- 第一次的余数 A' ( A'1, A'0 )
                ^pppppppp pppppppp p
                 --------------------------
                 ...
                          aaaaaaaa aaaaaaaa <- 结果 A ( A1, A0 )由此与一字节的情况比较,将两个字节分开计算如下:
    先算高字节:
        dddddddd 00000000 00000000 00000000 <- D1, 0, 0, 0
       ^pppppppp pppppppp p                 <- P
        -----------------------------------
        ...
                 aaaaaaaa aaaaaaaa          <- 高字节部分余数 PHA1, PHA0此处的部分余数与前面两字节算法中的第一次余数有如下关系,即 A'1 = PHA1 ^ D0, A'0 = PHA0:
                 aaaaaaaa aaaaaaaa          <- PHA1, PHA0
                ^dddddddd                   <- D0
                 -----------------
                 aaaaaaaa aaaaaaaa          <- A'1, A'0低字节的计算:
                 aaaaaaaa 00000000 00000000 <- A'1, 0, 0
                ^pppppppp pppppppp p        <- P
                 --------------------------
                 ...
                          aaaaaaaa aaaaaaaa <- 低字节部分余数 PLA1, PLA0
                         ^aaaaaaaa          <- A'0 , 即 PHA0
                          -----------------
                          aaaaaaaa aaaaaaaa <- 最后的 CRC ( A1, A0 )总结以上内容可得规律如下:
    设部分余数函数
        PA = f( d )
    其中 d 为一个字节的数据(注意,除非 n = 0 ,否则就不是原始数据,见下文)
    第 n 次的部分余数
        PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( d )
    其中的
        d = ( PA( n - 1 ) >> 8 ) ^ D( n )
    其中的 D( n ) 才是一个字节的原始数据。公式如下:
        PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( ( PA( n - 1 ) >> 8 ) ^ D( n ) )可以注意到函数 f( d ) 的参数 d 为一个字节,对一个确定的多项式 P, f( d ) 的返回值
    是与 d 一一对应的,总数为 256 项,将这些数据预先算出保存在表里,f( d )就转换为一
    个查表的过程,速度也就可以大幅提高,这也就是查表法计算 CRC 的原理,在 CRC_16 和
    CRC_32 两个函数的循环中的语句便是上面那个公式。再来看 CRC 表是如何计算出来的,即函数 f( d ) 的实现方法。分析前面一个字节数据的
    计算过程可发现,d 对结果的影响只表现为对 P 的移位异或,看计算过程中的三个 8 位
    的列中只有低两个字节的最后结果是余数,而数据所在的高 8 位列最后都被消去了,因其
    中的运算均为异或,不产生进位或借位,故每一位数据只影响本列的结果,即 d 并不直接
    影响结果。再将前例变化一下重列如下:
        11011000
        --------------------------
        10001000 00010000 1        // P
       ^ 1000100 00001000 01       // P
       ^  000000 00000000 000      // 0
       ^   10001 00000010 0001     // P
       ^    0000 00000000 00000    // 0
       ^     100 01000000 100001   // P
       ^      00 00000000 0000000  // 0
       ^       1 00010000 00100001 // P
               -------------------
                 01001010 01110101现在的问题就是如何根据 d 来对 P 移位异或了,从上面的例子看,也可以理解为每步
    移位,但根据 d 决定中间余数是否与 P 异或。从前面原来的例子可以看出,决定的条
    件是中间余数的最高位为0,因为 P 的最高位一定为1,即当中间余数与 d 相应位异或
    的最高位为1时,中间余数移位就要和 P 异或,否则只需移位即可。具体做法见程序中
    的 BuildTable16 和 BuildTable32 两个函数,其方法如下例(上例的变形,注意其中
    空格的移动表现了 d 的影响如何被排除在结果之外):    d --------a--------
        1 00000000 00000000 <- HSB = 1
          0000000 000000000 <- a <<= 1
          0001000 000100001 <- P, CRC-CCITT 不含最高位的 1
          -----------------
        1 0001000 000100001
          001000 0001000010
          000100 0000100001
          -----------------
        0 001100 0001100011 <- HSB = 0
          01100 00011000110
          -----------------
        1 01100 00011000110 <- HSB = 1
          1100 000110001100
          0001 000000100001
          -----------------
        1 1101 000110101101 <- HSB = 0
          101 0001101011010
          -----------------
        0 101 0001101011010 <- HSB = 1
          01 00011010110100
          00 01000000100001
          -----------------
        0 01 01011010010101 <- HSB = 0
          1 010110100101010
          -----------------
        0 1 010110100101010 <- HSB = 1
           0101101001010100
           0001000000100001
          -----------------
           0100101001110101 <- CRC结合这些,前面的程序就好理解了。至于 32 位 CRC 的计算与 16 相似,就不多加说明,请参考源程序。
          
    [Mental Studio]猛禽 Aug.9-2k