crc 检验算法

CRC校验算法就是我们计网上所学的CRC冗余检验算法

一、CRC8校验算法

CRC8检验算法的标准生成多项式

1、标准生成多项式

CRC-8       x8+x5+x4+1              0x310x131)
CRC-8       x8+x2+x1+1              0x070x107)
CRC-8       x8+x6+x4+x3+x2+x1       0x5E0x15E//我们在实际的编程中最高位正好是用不到的

2、代码实现(标准算法)

#include <iostream>

using namespace std;


unsigned char En_CRC (unsigned char *ptr, unsigned char len)
{
    unsigned char i; 
    unsigned char crc=0x00; // 计算的初始crc值

    while(len--)
    {
        crc ^= *ptr++;  // 每次先与需要计算的数据异或,计算完指向下一数据 
        for (i=8; i>0; --i)    //这就是大名鼎鼎的模2运算
        { 
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x31;        //CRC-8标准生成多项式       x8+x5+x4+1              0x31(0x131)
            else
                crc = (crc << 1);
        }
    }

    return (crc); 
}
int main(){
    
    unsigned char cip_crc[] = {0x11};
    cout<<hex<<(int)En_CRC(cip_crc,1);
    return 0;
}

3、代码实现(查表法)

//二、查表法
//首先计算0x00~0xFF每一个字节的crc校验结果 
//然后查表

#include <iostream>

using namespace std;

unsigned char cal_table_high_first(unsigned char value)
{
    unsigned char i, crc;

    crc = value;
    // 数据往左移了8位,需要计算8次 
    for (i=8; i>0; --i)
    { 
        if (crc & 0x80)  //判断最高位是否为1 
        {
        // 最高位为1,不需要异或,往左移一位,然后与0x31异或 
        // 0x31(多项式:x8+x5+x4+1,100110001),最高位不需要异或,直接去掉 
            crc = (crc << 1) ^ 0x31;        }
        else
        {
            /// 最高位为0时,不需要异或,整体数据往左移一位 
            crc = (crc << 1);
        }
    }

    return crc;
}
void create_crc_table()
{
    unsigned short i;
    unsigned char j;

    for (i=0; i<=0xFF; i++)
    {
        if (0 == (i%16))
            printf("\n");

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

    while (len--)
    {
        crc = crc_table[crc ^ *ptr++];
    }
    return (crc);
}
int main(){
    create_crc_table();
    
    unsigned char cip_crc[] = {0x11};
    cout<<endl;
    cout<<hex<<(int)cal_crc_table(cip_crc,1)<<endl;
    
    return 0;
}

二、CRC32

CRC32和CRC8原理几乎一致,这里直接给出代码
代码实现(查表法)(顺序表)
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
 
uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len)
{
    static uint32_t table[256];
    static int have_table = 0;
    uint32_t rem;
    uint8_t octet;
    int i, j;
    const char *p, *q;
 
    /* This check is not thread safe; there is no mutex. */
    if (have_table == 0) {
        /* Calculate CRC table. */
        for (i = 0; i < 256; i++) {
            rem = i;  /* remainder from polynomial division */
            for (j = 0; j < 8; j++) {
                if (rem & 1) {            //本来是要给buff[i]补24个0,然后rem & 0x80000000 的,但实际编程发现,这两个正好可以省去// 
                    rem >>= 1;
                    rem ^= 0xedb88320;
                } else
                    rem >>= 1;
            }
            table[i] = rem;
        }
        have_table = 1;
    }
 
    crc = ~crc; //这个数据。。。赋值为 0xffffffff //主要是为了满足32位 
    q = buf + len;
    for (p = buf; p < q; p++) {
        octet = *p;  /* Cast to unsigned octet. */
        crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];  //右移8位的目的是一个字符一个字符的迭代  
    }
    return ~crc; //正序的顺序表结果别忘取逆反
} 
 
int main()
{
    const char *s = "1";
    printf("%p\n", rc_crc32(0, s, strlen(s)));
 
    return 0;
}

 

参考链接:

 
posted @ 2022-07-12 18:42  TLSN  阅读(543)  评论(0)    收藏  举报