大家好,欢迎来到IT知识分享网。
本文仅用于本人学习记录,参考摘录了以下大佬的文章:
CRC8算法_算法_简单的过客-GitCode 开源社区 (csdn.net)
CRC算法原理、推导及实现 – QIYUEXIN – 博客园 (cnblogs.com)
目录
1.CRC8标准生成多项式
CRC-8 x8+x5+x4+1 0x31(0x131) CRC-8 x8+x2+x1+1 0x07(0x107) CRC-8 x8+x6+x4+x3+x2+x1 0x5E(0x15E)
注:由于多项式的最高为都为1,并且在代码的crc8计算中,最高位也是不使用的,所以在多项式记录时都去掉了最高位。
2.CRC校验算法
CRC校验算法,简而言之就是把需要校验的数据与多项式进行循环异或(XOR),XOR的方式与数据传输方式的高位先行(MSB)和低位先行(LSB)有关。
对于MSB:XOR从数据的高位开始,暂时定义为顺序异或;
对于LSB:XOR从数据的低位开始,暂时定义为反序异或;
两种不同的异或方式,即使对应相同的多项式,计算出来的结果也不一样。
3.算法推导
CRC的算法是基于除法,但不能直接使用除法运算,由于待校验的数据可能会很长,而MCU可能并没有这么大的寄存器;
3.1 仿人算方法
现在我们假设一个消息数据为,选取除数为10011,使用CRC算法将消息除以poly:
= Quotient (nobody cares about the quotient) _______________ 10011 ) 000 = Augmented message ( + 0000) =Poly 10011,,.,,..|. -----,,.,,|... 10011,.,,|.|. 10011,.,,|... -----,.,,|.|. 10110... 10011.|. -----... 010100. 10011. -----. 01110 00000 ----- 1110 = Remainder = THE CHECKSUM!!!!
除数poly的左边的高位的作用其实是给人看的(实际上参与运算的是0011),目的是干掉当前最高位的被除数,本质上是让poly和被除数对齐,然后开始XOR运算。
那么什么情况算是对齐呢? 从例子上看,当被除数和除数的最高位都是1时,就算是对齐了。因此当多项式为0x131()时,实际参与运算的是0x31(00)
转换成算法的思路就是,你也可以理解成一长串的数据不断的从右边移位到寄存器中,当寄存器最左边溢出的数值是1的时候,那么当前寄存器的数据就可以和poly异或运算了,用算法表示,大概是这样:
3 2 1 0 Bits +---+---+---+---+ Pop! <-- | | | | | <----- Augmented message +---+---+---+---+ 1 0 0 1 1 = The Poly
4.直接计算法:
typedef unsigned char uint8_t; typedef unsigned short int uint16_t; #define CRC8_POLYNOMIAL 0x31 /*计算多个字节CRC8校验值的函数*/ uint8_t cal_bytes_crc8(uint8_t *data, uint8_t len){ uint8_t crc8 = 0x00; /* 计算的初始crc值 */ uint8_t i ; while(len--){ crc8 ^= *data++; /* 每次先与需要计算的数据异或,计算完指向下一数据 */ for (i = 8; i > 0; --i) { /* 下面这段计算过程与计算一个字节crc一样 */ crc8 = ( crc8 & 0x80 ) ? (crc8 << 1) ^ CRC8_POLYNOMIAL : (crc8 << 1); } } return crc8 ; }
上面的crc计算是纯采用逻辑运行的方式,可以看到,需要的运行量也是不少的,每一个字节都需要进行8次判断、移位、或异或操作。可以采用查表法,大大减少计算量,先计算0x00~0xFF每一个字节的crc校验结果,后面就可以通过表来查出每个字节的crc结果,大大减少计算量。
5.查表法
uint8_t cal_table_high_first(uint8_t value) { uint8_t i, crc=0x00; crc = value; /* 数据往左移了8位,需要计算8次 */ for (i=8; i>0; --i){ crc = ( crc & 0x80 ) /* 判断最高位是否为1 */ /* 最高位为1,不需要异或,往左移一位,然后与0x31异或 */ /* 0x31(多项式:x8+x5+x4+1,),最高位不需要异或,直接去掉 */ ? (crc << 1) ^ CRC8_POLYNOMIAL /* 最高位为0时,不需要异或,整体数据往左移一位 */ : (crc << 1); } return crc; } // 下面是一个表生成程序: void create_crc_table(void) { uint16_t i; uint8_t 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校验值*/ } } // 按照多项式 X^8+X^2+X^1+1 生成。 static const unsigned int crc8_table[256] = { 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 }; //采用查表法计算crc代码如下: uint8_t cal_crc_table(uint8_t *data, uint8_t len){ uint8_t crc8 = 0x00; while (len --){ crc8 = crc8_table[crc8 ^ *data++]; } return crc8 ; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112983.html