crc 订阅
循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。 展开全文
循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。
信息
简    称
CRC
有关术语
循环冗余校验码
原    理
除法及余数的原理来作错误侦测
中文名
循环冗余校验
目    的
确保传输的数据准确无误
外文名
Cyclic Redundancy Check
CRC简介
在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有奇偶校验、因特网校验和循环冗余校验等。循环冗余校验是一种用于校验通信链路上数字传输准确性的计算方法(通过某种数学运算来建立数据位和校验位的约定关系的 [1]  )。发送方计算机使用某公式计算出被传送数据所含信息的一个值,并将此值 附在被传送数据后,接收方计算机则对同一数据进行 相同的计算,应该得到相同的结果。如果这两个 CRC结果不一致,则说明发送中出现了差错,接收方计算机可要求发送方计算机重新发送该数据。在计算机网络通信中运用CRC校验时相对于其他校验方法就有一定的优势。CRC可以高比例的纠正信息传输过程中的错误,可以在极短的时间内完成数据校验码的计算,并迅速完成纠错过程,通过数据包自动重发的方式使得计算机的通信速度大幅提高,对通信效率和安全提供了保障。由于 CRC 算法检验的检错能力极强,且检测成本较低,因此在对于编码器和电路的检测中使用较为广泛。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。
收起全文
精华内容
下载资源
问答
  • CRC

    2018-06-14 10:51:00
    CRC 在线工具:http://www.ip33.com/crc.html 1.CRC16_XMODEM x16+x12+x5+1 多项式:1021 初始值:0000 C# public static int CRC16_XMODEM(byte[] datas) { int crc = 0x0000;//初始...

    CRC 在线工具:http://www.ip33.com/crc.html

     

    1.CRC16_XMODEM  x16+x12+x5+1

      多项式:1021

       初始值:0000

     C#

       

     public static int CRC16_XMODEM(byte[] datas)
            {
                int crc = 0x0000;//初始值
                int crcPoly = 0x1021;
                for(int i=0;i<datas.Length;i++)
                {       
                    crc ^= (datas[i] << 8);            
    
                    for(int j=0;j<8;j++)
                    {                  
                      
                        if ((crc & 0x8000)>0)
                        {                      
                            crc = (ushort)((crc << 1) ^ crcPoly);
                        }
                        else
                        {                      
                            crc = (ushort)(crc << 1);
                        }
                    }
                }
                return crc;
            }

    c++

    uint16_t MainWindow::crc16_xmodem(uint8_t *data, int length)
    {
       uint8_t i;
       uint16_t crc = 0;       // Initial value
       while(length--)
       {
           crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;for (i = 0; i < 8; ++i)
            {
                if ( crc & 0x8000 )
                {              
                   crc = (crc << 1) ^ 0x1021;
                }
                else
                {            
                    crc <<= 1;
                }
           }
        }
        return crc;
    }

     

      

    转载于:https://www.cnblogs.com/ike_li/p/9182002.html

    展开全文
  • crc

    2015-11-30 22:30:37
    1、CRC简介 CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。接收...

    1、CRC简介

    CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。接收端根据同样的规则校验,以确定传送中是否出错。接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。2、计算整个k+r位的CRC码,若为0,则接收正确。
    CRC码有多种检验位数,8位、16位、32位等,原理相同。16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(即乘以2的16次方后),除以一个多项式,最后所得到的余数就是CRC码。
    求CRC码所采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。这一点要仔细理解,是编程的基础。
    CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1
    CRC-CCITT: (由欧洲CCITT推荐) G(X) = X16 + X12 + X5 + 1
    CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1

    2、按位计算CRC

    采用CRC-CCITT多项式,多项式为0x11021,C语言编程时,参与计算为0x1021,这个地方得深入思考才能体会其中的奥妙,分享一下我的思路:当按位计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,将二进制序列数左移16位,即为1001 1010 1010 1111 (0000 0000 0000 0000),实际上该二进制序列可拆分为1000 0000 0000 0000 (0000 0000 0000 0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000) + 1 0000 0000 0000 (0000 0000 0000 0000) + …… 
    现在开始分析运算:
    <1>对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留;
    <2>接着对第二个二进制分序列求余数,将第一步运算的余数*2后再和第二个二进制分序列一起对0x11021求余,这一步理解应该没什么问题。如果该分序列为0,无需计算。
    <3>对其余的二进制序列求余与上面两步相同。
    <4>计算到最后一位时即为整个二进制序列的余数,即为CRC校验码。
    该计算方法相当于对每一位计算,运算过程很容易理解,所占内存少,缺点是一位一位计算比较耗时。
    下面给出C语言实现方法:

    复制代码代码如下:

    unsigned char test[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
    unsigned char len = 16;
    void main( void )
    {
       unsigned long temp = 0;
       unsigned int crc;
       unsigned char i;
       unsigned char *ptr = test;

       while( len-- ) {
          for(i = 0x80; i != 0; i = i >> 1) {
             temp = temp * 2;
             if((temp & 0x10000) != 0)
                temp = temp ^ 0x11021;

             if((*ptr & i) != 0) 
                temp = temp ^ (0x10000 ^ 0x11021);

         }
        ptr++;
       }
       crc = temp;
       printf("0x%x ",crc);
    }


    上面的程序根据运算分析而来,很容易理解。为了节约内存空间,我们对程序作进一步的简化。分析可知,当二进制序列中上一位计算的余数第15bit位为1时,即( 上一位计算的余数 & 0x8000) != 0,计算本位时,上一位余数 * 2后可对0x11021作求余运算,然后再加上本位计算所得余数。这个很好理解,也就是说,打个比方,把它看作简单的除法,计算上一位时的余数乘以2后,如果比较大可以当被除数,就再去除除数求余。有一点和普通除法不同的是,因为多项式除法中采用不带借位的减法运算,所以0x10000也可以被0x11021除,余数并非为0x10000,而是0x1021。这个自己动手算一下就知道了。余数之和也是不带进位的加法运算,即异或。最后还强调一点,因为二进制序列是左移16位后参与运算的,所以,一直算到序列的最后一位也是可以被除的,这点大家要明白。下面给出简化后的C语言实现。
    复制代码代码如下:

    unsigned char test[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
    unsigned char len = 16;
    void main( void )
    {
       unsigned int crc = 0;
       unsigned char i;
       unsigned char *ptr = test;

       while( len-- ) {
          for(i = 0x80; i != 0; i = i >> 1) {
            if((crc & 0x8000) != 0) {
               crc = crc << 1;
               crc = crc ^ 0x1021;
            }
            else {
               crc = crc << 1;
            }
            if((*ptr & i) != 0) {
              crc = crc ^ 0x1021; 
            }
         }
         ptr++;
       }

       printf("0x%x ",crc);
    }


    上面这段程序网上较为常见,但冇得详细的解释。通过我上面的详细分析,如果对此段程序理解还有困难,可以对比一下没简化之前的程序,细细品味一哈,还是比较容易理解的。要是还理解不了,还是从头再看下,我码这么多字容易吗。。。。。
    按位计算CRC代码比较简单,所占内存少,但要一位一位去计算,下面再介绍一种按字节查表快速计算CRC的方法。

    3、按字节计算CRC

    有了上面按位计算的知识,理解这个就是小case了。还是举前面的例子:当字节计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,即0x9a9f时,将二进制序列数左移16位,即为0x9a9f(0 0 0 0),实际上该二进制序列可拆分为0x9a00(0 0 0 0) + 0x009f(0 0 0 0),分析计算时和上面的步骤一样,唯一不同的是计算中上一步的余数CRC要乘以2的八次方参与下一步的运算,这个应该好理解撒。为了简化编程,将计算中的CRC拆成高八位和低八位的形式,高八位的值直接与本位值相加求余,低八位的值乘以2的八次方后作为余数和计算得的余数相加。为了提高计算速度,我们把8位二进制序列数的CRC全部计算出来,放在一个表中,采用查表法可大大提高计算速度。
    表是怎么得到的呢?当然是计算出来的,下面的程序给出了多项式是0x11021的计算程序。

    复制代码代码如下:

    void main( void )
    {
       unsigned int crc = 0;
       unsigned char i;
       unsigned int j;

       for(j = 0; j < 256; j++) {
          crc = 0;
          for(i = 0x80; i != 0; i = i >> 1) {
             if((crc & 0x8000) != 0) {
                crc = crc << 1;
                crc = crc ^ 0x1021;
            }
            else {
                crc = crc << 1;
            }
            if((j & i) != 0) {
                crc = crc ^ 0x1021;
            }
       }
       printf("0x");
       if(crc < 0x10) {
          printf("000");
       }
       else if(crc < 0x100) {
          printf("00");
       }
       else if(crc < 0x1000) {
          printf("0");
       }

       printf("%x, ",crc);
       }
    }


    如果你不是使用的0x11021多项式,只需把程序中0x1021换成其他的就可以了。后面的几个printf语句为了控制使生成的表比较整齐,如果无所谓,可直接用printf("0x%x, ",crc);代替。生成的表如下:
    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,
    好了,我们来写按字节计算的源程序:
    复制代码代码如下:

    unsigned char test[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
    unsigned char len = 16;
    unsigned int crc_table[256] ={
    x0000, 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};
    void main(void)
    {
       unsigned int crc = 0;
       unsigned char crc_H8;
       unsigned char *ptr = test;

       while( len-- ) {
          crc_H8 = (unsigned char)(crc >> 8);
          crc = crc << 8;
          crc = crc ^ crc_table[ crc_H8 ^ *ptr];
          ptr++;
       }
       printf("0x%x ",crc);
    }


    4、按半字节计算CRC

    是不是感觉上面的表太大了,不是很爽,我们再来改进一下,按半字节计算,原理我就不赘述了,程序如下:

    复制代码代码如下:

    unsigned char test[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
    unsigned char len = 16;
    unsigned int crc_table[16] =
    {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
    };
    void main(void)
    {
    unsigned int crc = 0;
    unsigned char crc_H4;
    unsigned char *ptr = test;

    while( len-- )
    {
    crc_H4 = (unsigned char)(crc >> 12);
    crc = crc << 4;
    crc = crc ^ crc_table[ crc_H4 ^ (*ptr >> 4)];
    crc_H4 = (unsigned char)(crc >> 12);
    crc = crc << 4;
    crc = crc ^ crc_table[ crc_H4 ^ (*ptr & 0x0f)];
    ptr++;
    }
    printf("0x%x ",crc);
    }

    展开全文
  • crc计算器crc计算器
  • 各种CRC源码 CRC8 CRC16 CRC32 CRCCCITT CRCDNP CRCKRMIT CRCSICK NMEA_CHK
  • CRC8\CRC10\CRC11\CRC12\CRC13\CRC14\CRC15\CRC16\CRC24\CRC31\CRC32\CRC64等各种类型的CRC计算工具,方便快捷。
  • CRC8 CRC16

    2018-03-04 11:10:46
    CRC-8 (正序) CRC-8 (逆序) CRC-16 (0xA001) CRC-16 (0x8005) CRC-16 (Modbus) CRC-CCITT (XModem) CRC-CCITT (Kermit) CRC-DNP IntelHex BCC (异或校验) LRC (纵向冗余校验) CRC-32 (循环冗余)
  • 添加CRCCRC校验

    2019-08-14 19:47:59
    添加CRCCRC校验的matlab源码。 包含Crc11Decode和Crc11Encode两个文件
  • CRC计算器,实现了CRC4、CRC5、CRC6、CRC7、CRC8、CRC16、CRC32等21种算法
  • 答:作二进制除法,1101011011 0000除以10011(这是根据P(X)=X^4+X+1得出的)得余数1110 添加的检验序列是1110作二进制除法,两种错误均可发展仅仅采用了CRC检验,缺重传机制,数据链路层的传输还不是可靠的传输。...

    答:作二进制除法,1101011011 0000除以10011(这是根据P(X)=X^4+X+1得出的)得余数1110   

                 

    添加的检验序列是1110

    作二进制除法,两种错误均可发现发展

    仅仅采用了CRC检验,缺重传机制,数据链路层的传输还不是可靠的传输。

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

    展开全文
  • crc资料crc资料crc资料

    2011-06-14 01:16:31
    crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc资料crc...
  • CRC 计算器

    2018-08-16 11:05:23
    CRC计算器,实现了CRC4、CRC5、CRC6、CRC7、CRC8、CRC16、CRC32等21中算法,可以用来计算CRC校验和,很方便
  • CRC计算 crc.c

    2015-08-01 22:33:43
    CRC计算 crc.c 16bit crc calculation
  • CRC4-ITU X4+X+1 CRC5-EPC X4+X3+1 CRC5-ITU X5+X4+X2+1 CRC5-USB X5+X2+1 CRC6-ITU X5+X2+1 CRC7-MMC X7+X3+1 CRC8 X8+X2+X+1 CRC8-ITU X8+X2+X+1 CRC8-ROCH X8+X2+X+1 CRC8-MAXIM X8+X5+X4+1 CRC16-IBM X16+X15+X2...
  • CRC16常见几个标准的算法及C语言实现

    万次阅读 多人点赞 2017-01-10 10:56:00
    CRC16常见的标准有以下几种,被用在各个规范中,其算法原理基本一致,就是在数据的输入和输出有所差异,下边把这些标准的差异列出,并给出C语言的算法实现。 CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0x...

    CRC16常见的标准有以下几种,被用在各个规范中,其算法原理基本一致,就是在数据的输入和输出有所差异,下边把这些标准的差异列出,并给出C语言的算法实现。

    CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,结果与0x0000异或

    CRC16_CCITT_FALSE:多项式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在后,高位在前,结果与0x0000异或

    CRC16_XMODEM:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在后,高位在前,结果与0x0000异或

    CRC16_X25:多项式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在前,高位在后,结果与0xFFFF异或

    CRC16_MODBUS:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0x0000异或

    CRC16_IBM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,结果与0x0000异或

    CRC16_MAXIM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,结果与0xFFFF异或

    CRC16_USB:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0xFFFF异或

     

    模式

    多项式

    初始值

    数据位序

    结果处理

    CRC16_CCITT

    x16+x12+x5+1(0x1021)

    0x0000

    低位在前,高位在后

    与0x0000异或

    CRC16_CCITT_FALSE

    x16+x12+x5+1(0x1021)

    0xFFFF

    低位在后,高位在前

    与0x0000异或

    CRC16_XMODEM

    x16+x12+x5+1(0x1021)

    0x0000

    低位在后,高位在前

    与0x0000异或

    CRC16_X25

    x16+x12+x5+1(0x1021)

    0xFFFF

    低位在前,高位在后

    与0xFFFF异或

    CRC16_ MODBUS

    x16+x15+x2+1(0x8005)

    0xFFFF

    低位在前,高位在后

    与0x0000异或

    CRC16_ IBM

    x16+x15+x2+1(0x8005)

    0x0000

    低位在前,高位在后

    与0x0000异或

    CRC16_ MAXIM

    x16+x15+x2+1(0x8005)

    0x0000

    低位在前,高位在后

    与0xFFFF异或

    CRC16_ USB

    x16+x15+x2+1(0x8005)

    0xFFFF

    低位在前,高位在后

    与0xFFFF异或

    多项式产生:
    如x16+x12+x5+1
    x16表示第16位为1,x5表示第5位为1
    (1 << 16) | (1 << 12) | (1 << 5) | (1) = 0x11021
    但是CRC16只取低16位,写成16进制数就是 0x1021

    CRC16的算法原理:

    1.根据CRC16的标准选择初值CRCIn的值。

    2.将数据的第一个字节与CRCIn高8位异或。

    3.判断最高位,若该位为 0 左移一位,若为 1 左移一位再与多项式Hex码异或。

    4.重复3直至8位全部移位计算结束。

    5.重复将所有输入数据操作完成以上步骤,所得16位数即16位CRC校验码。

    根据算法原理与标准要求就能简单的写出具体程序:

    CRC算法参数模型解释: 
        NAME:参数模型名称。 
        WIDTH:宽度,即CRC比特数。 
        POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生    成项是0x104C11DB7。 
        INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。 
        REFIN:待测数据的每个字节是否按位反转,True或False。 
        REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。 
        XOROUT:计算结果与此参数异或后得到最终的CRC值。
        Alias:别名及其应用范围。
    /****************************Info********************************************** 
     * Name:    CRC-16/CCITT        x16+x12+x5+1 
     * Width:	16
     * Poly:    0x1021 
     * Init:    0x0000 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x0000 
     * Alias:   CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT 
     *****************************************************************************/ 
    #if 0
    unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x1021;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else 
    //这里为了效率,我们不需要将所有Refin和refout为true的输入输出数据移位转换
    //只需要将poly二项式转换后,运算时将左移变为右移
    unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x1021;
    	unsigned char wChar = 0;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/CCITT-FALSE   x16+x12+x5+1 
     * Width:	16 
     * Poly:    0x1021 
     * Init:    0xFFFF 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x0000 
     * Note: 
     *****************************************************************************/ 
    unsigned short CRC16_CCITT_FALSE(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x1021;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++) << 8;
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin);
    }
    /****************************Info********************************************** 
     * Name:    CRC-16/XMODEM       x16+x12+x5+1 
     * Width:	16 
     * Poly:    0x1021 
     * Init:    0x0000 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x0000 
     * Alias:   CRC-16/ZMODEM,CRC-16/ACORN 
     *****************************************************************************/ 
    unsigned short CRC16_XMODEM(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x1021;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= (*(data++) << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin);
    }
    /****************************Info********************************************** 
     * Name:    CRC-16/X25          x16+x12+x5+1 
     * Width:	16 
     * Poly:    0x1021 
     * Init:    0xFFFF 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0XFFFF 
     * Note: 
     *****************************************************************************/
    #if 0 
    unsigned short CRC16_X25(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x1021;
    	unsigned char wChar = 0;
    
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin^0xFFFF);
    }
    #else 
    unsigned short CRC16_X25(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x1021;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin^0xFFFF);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/MODBUS       x16+x15+x2+1 
     * Width:	16 
     * Poly:    0x8005 
     * Init:    0xFFFF 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x0000 
     * Note: 
     *****************************************************************************/
    #if 0 
    unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x8005;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else 
    unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x8005;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/IBM          x16+x15+x2+1 
     * Width:	16 
     * Poly:    0x8005 
     * Init:    0x0000 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x0000 
     * Alias:   CRC-16,CRC-16/ARC,CRC-16/LHA 
     *****************************************************************************/ 
    #if 0
    unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x8005;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else 
    unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x8005;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/MAXIM        x16+x15+x2+1 
     * Width:	16 
     * Poly:    0x8005 
     * Init:    0x0000 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0xFFFF 
     * Note: 
     *****************************************************************************/
    #if 0
    unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x8005;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin^0xFFFF);
    }
    #else 
    unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x8005;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin^0xFFFF);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/USB          x16+x15+x2+1 
     * Width:	16 
     * Poly:    0x8005 
     * Init:    0xFFFF 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0xFFFF 
     * Note: 
     *****************************************************************************/ 
    #if 0
    unsigned short CRC16_USB(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x8005;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin^0xFFFF);
    }
    #else 
    unsigned short CRC16_USB(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0xFFFF;
    	unsigned short wCPoly = 0x8005;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin^0xFFFF);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-16/DNP          x16+x13+x12+x11+x10+x8+x6+x5+x2+1 
     * Width:	16 
     * Poly:    0x3D65 
     * Init:    0x0000 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0xFFFF 
     * Use:     M-Bus,ect. 
     *****************************************************************************/  
    #if 0
    unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x3D65;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 8);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x8000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint16(&wCRCin,&wCRCin);
    	return (wCRCin^0xFFFF) ;
    }
    #else
    unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen)
    {
    	unsigned short wCRCin = 0x0000;
    	unsigned short wCPoly = 0x3D65;
    	
    	InvertUint16(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = (wCRCin >> 1);
    		}
    	}
    	return (wCRCin^0xFFFF);
    }
    #endif

     

    /****************************Info********************************************** 
     * Name:    InvertUint8 
     * Note: 	把字节颠倒过来,如0x12变成0x48
    			0x12: 0001 0010
    			0x48: 0100 1000
     *****************************************************************************/
    void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)
    {
    	int i;
    	unsigned char tmp[4]={0};
    
    	for(i=0;i< 8;i++)
    	{
    		if(srcBuf[0]& (1 << i))
    		tmp[0]|=1<<(7-i);
    	}
    	dBuf[0] = tmp[0];
    	
    }
    void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
    {
    	int i;
    	unsigned short tmp[4]={0};
    
    	for(i=0;i< 16;i++)
    	{
    		if(srcBuf[0]& (1 << i))
    		tmp[0]|=1<<(15 - i);
    	}
    	dBuf[0] = tmp[0];
    }
    void InvertUint32(unsigned int *dBuf,unsigned int *srcBuf)
    {
    	int i;
    	unsigned int tmp[4]={0};
    	
    	for(i=0;i< 32;i++)
    	{
    		if(srcBuf[0]& (1 << i))
    		tmp[0]|=1<<(31 - i);
    	}
    	dBuf[0] = tmp[0];
    }
    

    具体验证使用这个工具,内含CRC算法的计算,和后边的博客中提到的其他算法的工具合集

    加密解密算法工具集

    CRC计算器CRC_Calc

    在这个基础上也加入CRC32 的校验算法

    /****************************Info********************************************** 
     * Name:    CRC-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 
     * Width:	32 
     * Poly:    0x4C11DB7 
     * Init:    0xFFFFFFF 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0xFFFFFFF 
     * Alias:   CRC_32/ADCCP 
     * Use:     WinRAR,ect. 
     *****************************************************************************/  
    #if 0
    unsigned int CRC32(unsigned char *data, unsigned int datalen)
    {
    	unsigned int wCRCin = 0xFFFFFFFF;
    	unsigned int wCPoly = 0x04C11DB7;
    	unsigned int wChar = 0;
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8((unsigned char *)&wChar,(unsigned char *)&wChar);
    		wCRCin ^= (wChar << 24);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80000000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint32(&wCRCin,&wCRCin);
    	return (wCRCin ^ 0xFFFFFFFF) ;
    }
    #else
    unsigned int CRC32(unsigned char *data, unsigned int datalen)
    {
    
    	unsigned int wCRCin = 0xFFFFFFFF;
    	unsigned int wCPoly = 0x04C11DB7;
    
    	InvertUint32(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin ^ 0xFFFFFFFF) ;
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-32/MPEG-2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 
     * Width:	32 
     * Poly:    0x4C11DB7 
     * Init:    0xFFFFFFF 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x0000000 
     * Note: 
     *****************************************************************************/ 
    unsigned int CRC32_MPEG(unsigned char *data, unsigned int datalen)
    {
    
    	unsigned int wCRCin = 0xFFFFFFFF;
    	unsigned int wCPoly = 0x04C11DB7;
    	unsigned int wChar = 0;
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		wCRCin ^= (wChar << 24);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80000000)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin) ;
    }

    对于CRC32可能还有其他的多项式和初始值和结果值是否需要异或以及输入数据是否需要位序倒转等要求在源码中修改

    本次在CRC算法的基础上加入CRC-4,5,6,7,8的各个算法实现:

    /****************************Info********************************************** 
     * Name:    CRC-4/ITU	x4+x+1 
     * Width:	4
     * Poly:    0x03 
     * Init:    0x00 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
    unsigned char CRC4_ITU(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x03;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly << 4);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    /****************************Info********************************************** 
     * Name:    CRC-5/EPC	x5+x3+1 
     * Width:	5
     * Poly:    0x09 
     * Init:    0x09 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
    unsigned char CRC5_EPC(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x09<<3;
    	unsigned char wCPoly = 0x09<<3;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin >> 3);
    }
    /****************************Info********************************************** 
     * Name:    CRC-5/USB	x5+x2+1 
     * Width:	5
     * Poly:    0x05 
     * Init:    0x1F 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x1F 
     * Note: 
     *****************************************************************************/
    #if 0
    unsigned char CRC5_USB(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x1F<<3;
    	unsigned char wCPoly = 0x05;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly << 3);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin^0x1F);
    }
    #else
    unsigned char CRC5_USB(unsigned char *data, unsigned int datalen)  
    {  
    	unsigned char wCRCin = 0x1F;
    	unsigned char wCPoly = 0x05;
    	
    	InvertUint8(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin^0x1F); 
    } 
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-5/ITU	x5+x4+x2+1  
     * Width:	5
     * Poly:    0x15 
     * Init:    0x00 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
     #if 0
    unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x15;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly << 3);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else
    unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen)  
    {  
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x15;
    	
    	InvertUint8(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin); 
    } 
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-6/ITU	x6+x+1 
     * Width:	6
     * Poly:    0x03 
     * Init:    0x00 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
    unsigned char CRC6_ITU(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x03;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly << 2);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    /****************************Info********************************************** 
     * Name:    CRC-7/MMC           x7+x3+1  
     * Width:	7
     * Poly:    0x09 
     * Init:    0x00 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x00 
     * Use:     MultiMediaCard,SD,ect. 
     *****************************************************************************/
    unsigned char CRC7_MMC(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x09;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ (wCPoly<<1);
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin>>1);
    }
    /****************************Info********************************************** 
     * Name:    CRC-8               x8+x2+x+1 
     * Width:	8 
     * Poly:    0x07 
     * Init:    0x00 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
    unsigned char CRC8(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x07;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin);
    }
    /****************************Info********************************************** 
     * Name:    CRC-8/ITU           x8+x2+x+1 
     * Width:	8 
     * Poly:    0x07 
     * Init:    0x00 
     * Refin:   False 
     * Refout:  False 
     * Xorout:  0x55 
     * Alias:   CRC-8/ATM 
     *****************************************************************************/
    unsigned char CRC8_ITU(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x07;
    	
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	return (wCRCin^0x55);
    }
    /****************************Info********************************************** 
     * Name:    CRC-8/ROHC          x8+x2+x+1 
     * Width:	8 
     * Poly:    0x07 
     * Init:    0xFF 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x00 
     * Note: 
     *****************************************************************************/
    #if 0
    unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0xFF;
    	unsigned char wCPoly = 0x07;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 0);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else 
    unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0xFF;
    	unsigned char wCPoly = 0x07;
    	
    	InvertUint8(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin);
    }
    #endif
    /****************************Info********************************************** 
     * Name:    CRC-8/MAXIM         x8+x5+x4+1 
     * Width:	8 
     * Poly:    0x31 
     * Init:    0x00 
     * Refin:   True 
     * Refout:  True 
     * Xorout:  0x00 
     * Alias:   DOW-CRC,CRC-8/IBUTTON 
     * Use:     Maxim(Dallas)'s some devices,e.g. DS18B20 
     *****************************************************************************/ 
    #if 0
    unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x31;
    	unsigned char wChar = 0;
    	
    	while (datalen--) 	
    	{
    		wChar = *(data++);
    		InvertUint8(&wChar,&wChar);
    		wCRCin ^= (wChar << 0);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x80)
    				wCRCin = (wCRCin << 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin << 1;
    		}
    	}
    	InvertUint8(&wCRCin,&wCRCin);
    	return (wCRCin);
    }
    #else 
    unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen)
    {
    	unsigned char wCRCin = 0x00;
    	unsigned char wCPoly = 0x31;
    	
    	InvertUint8(&wCPoly,&wCPoly);
    	while (datalen--) 	
    	{
    		wCRCin ^= *(data++);
    		for(int i = 0;i < 8;i++)
    		{
    			if(wCRCin & 0x01)
    				wCRCin = (wCRCin >> 1) ^ wCPoly;
    			else
    				wCRCin = wCRCin >> 1;
    		}
    	}
    	return (wCRCin);
    }
    #endif

    最后附上代码,里面含有测试程序

    CRC-4,5,6,7,8,16,32算法.c

     

    展开全文
  • 我学习CRC32、CRC16、CRC 原理和算法的总结(与WINRAR 结果一致),里面详细描述了CRC原理,应用,及相应推导过程,是CRC讲得最全的,从入门到高阶及C语言写的例程都有!~~
  • eMMC SD crc7 crc16.c

    2020-09-21 17:06:44
    此文件中为eMMC和SD卡通信中crc7和crc16校验源码,还有一个SD卡应用中可计算不超过512字节数据的数据crc计算函数

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,137
精华内容 8,854
关键字:

crc