C++ CRC-CCITT 实施

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17196743/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:59:33  来源:igfitidea点击:

CRC-CCITT Implementation

c++cchecksumcrccrc16

提问by AlphabetaPhi

I am using the following function to generate a CRC sum and it doesn't appear to be returning the same checksum when compared to online CRC-CCITT calculators.

我正在使用以下函数来生成 CRC 和,与在线 CRC-CCITT 计算器相比,它似乎没有返回相同的校验和。

This function specifically uses the XMODEM CRC generation with a 0x8408 polynomial with an initial fcs of 0xFFFF.

该函数专门使用具有 0x8408 多项式且初始 fcs 为 0xFFFF 的 XMODEM CRC 生成。

uint16_t crc16(uint8_t byte, uint16_t fcs)
{
    uint8_t bit;

    for(bit=0; bit<8; bit++)
    {
        fcs ^= (byte & 0x01);
        fcs = (fcs & 0x01) ? (fcs >> 1) ^ 0x8408 : (fcs >> 1);
        byte = byte >> 1;
    }
    return fcs;
}

Am I doing something wrong? If I send 0xFF, or 0x00 I do not get the same checksum as I do on http://depa.usst.edu.cn/chenjq/www2/SDesign/JavaScript/CRCcalculation.htm

难道我做错了什么?如果我发送 0xFF 或 0x00,我不会得到与http://depa.usst.edu.cn/chenjq/www2/SDesign/JavaScript/CRCcalculation.htm上相同的校验和

printf("%04X\n", crc16(0x31, 0xFFFF)); //returns 2F8D

回答by Mark Adler

Take a look at Greg Cook's excellent catalog of CRCs. There is a variant often falsely identified as the CCITT CRC, which it isn't. That is what your code, with the 0xFFFFinitialization, appears to be computing, though reflected. The Kermit CRC is the actual CCITT CRC. To get the CCITT CRC, you should start with zero, not 0xFFFF. The XMODEM CRC is different still, like the Kermit CRC, but unreflected (so bits go in the top, and you exclusive-or with 0x1021).

看看Greg Cook 的优秀 CRC 目录。有一个变体经常被错误地识别为 CCITT CRC,但事实并非如此。这就是您的代码在0xFFFF初始化时似乎正在计算的内容,尽管已反映。Kermit CRC 是实际的 CCITT CRC。要获得 CCITT CRC,您应该从零开始,而不是0xFFFF. XMODEM CRC 仍然不同,就像 Kermit CRC 一样,但没有反映(因此位位于顶部,并且您与 异或0x1021)。

KERMIT
width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"

XMODEM
width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 name="XMODEM"

CRC-16/CCITT-FALSE
width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"

回答by sarvankumar_t

I have read your questions and I also had the similar problem like you.

我已经阅读了您的问题,我也遇到了与您类似的问题。

I have solved this issue for calculating CRC-CCITT in XMODEM. here I am attaching the sample program to calculate CRC-CCITT.

我已经解决了这个问题,用于在 XMODEM 中计算 CRC-CCITT。在这里我附上示例程序来计算 CRC-CCITT。

I have tried the data with the online converter and this program. Please use this if you wish.

我已经用在线转换器和这个程序尝试过数据。如果您愿意,请使用它。

unsigned short crc16(char *ptr, int count)
{
   int  crc;
   char i;
   crc = 0;
   while (--count >= 0)
   {
      crc = crc ^ (int) *ptr++ << 8;
      i = 8;
      do
      {
         if (crc & 0x8000)
            crc = crc << 1 ^ 0x1021;
         else
            crc = crc << 1;
      } while(--i);
   }
   return (crc);
}

CRC should be defined as unsigned short since the crc16function returns an unsigned short. CRC is defined as an int which on most systems is 4 bytes.

CRC 应定义为 unsigned short,因为该crc16函数返回一个 unsigned short。CRC 被定义为一个 int,在大多数系统上是 4 个字节。

回答by Vincent

static const unsigned short CRC_CCITT_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
};

I use the following code to calculate a CRC-CCITT (0xFFFF):

我使用以下代码来计算 CRC-CCITT (0xFFFF):

unsigned short Calculate_CRC_CCITT(const unsigned char* buffer, int size)
{
    unsigned short tmp;
    unsigned short crc = 0xffff;

    for (int i=0; i < size ; i++)
    {
        tmp = (crc >> 8) ^ buffer[i];
        crc = (crc << 8) ^ CRC_CCITT_TABLE[tmp];
    }

    return crc;
}