• CRC8校验算法源码——C语言版


      本文以CRC8实际代码为例启发各位读者,如何编写一个CRC的校验算法。让各位读者直接跳过繁琐的原理说明阶段,快速应用到工程当中。

    一、例程介绍

            CRC的校验有很多很多种,掌握以下思路,写任何一个CRC的源生代码都应该没有问题。

       本文使用的示范代码为本人编写,算法为CRC-8-MAXIM,多项式为X^8+X^5+X^4+1,即0x31

    初始值为0xFF,结果异或值0x00,输入数据和输出数据均不反转。

    1.多项式计算的方法

        有很多人不知道这个0x31是怎么来的,这里为大家计算一下展开的话就是

    1*x^8+0*x^7+0*x^6+1*x^5+1*x^4+0*x^3+0*x^2+0*x^1+1*x^0 对应二进制1 0011 0001 即0x131

    CRC8校验取低字节,那么多项式的值就是0x31了

    1.反转解释

       意思就是将低位变高位,再进行计算

    例如:0001 1100 0010 1001 反转后得到的就是 0011 1000 1001 0100

    二、代码示例

    1.计算法

    1. #include <stdio.h>
    2. unsigned char CRC8_MAXIM(unsigned char *dat,unsigned int len){
    3. unsigned char crc_value=0xFF,j; //初始值为0xff,也有很多初始值为0x00的,此处可修改
    4. unsigned int i;
    5. for(i=0;i<len;i++){
    6. crc_value ^= *dat++;
    7. for(j=0;j<8;j++){
    8. if(crc_value&0x80){
    9. crc_value=(crc_value<<1)^0x31;//其余的CRC校验算法修改该多项式的值即可
    10. }else{
    11. crc_value=(crc_value<<1);
    12. }
    13. }
    14. }
    15. return crc_value;
    16. }
    17. /*使用示例*/
    18. int main(void)
    19. {
    20. unsigned char buff[2]={0xbe,0xef};
    21. printf("crc=%X\n", CRC8_MAXIM(buff,2));
    22. return 0;
    23. }

    2.查表法

            查表法的原理就是把已经计算出来的值放入一个数组内,这里教大家一个小技巧,用代码写代码,255个值总不能自己去一个个算出来手敲吧。

    调用刚刚的计算法函数,编写如下代码,然后在一个C在线编译工具打印出来即可

    1. int main(void)
    2. {
    3. unsigned int k=256; //因为本示例代码的初始值是0xff,所以这里要注意,表格要倒序
    4. //如果初始值是0x00,那表格应该换成正序的
    5. unsigned char buff[2]={0xbe,0xef};
    6. printf("unsigned char CRC8_MAXIM_TABLE[256]={ \n");
    7. while(k--){ /*初始化为0x00时应替换为 for(k=0;k<255;k++)*/
    8. printf("0x%.2x,",CRC8_MAXIM(&k,1));
    9. if(k%8==0){
    10. printf("\n");
    11. }
    12. }
    13. printf("}; \n");
    14. return 0;
    15. }

    打印出来的数组如下:

    1. unsigned char CRC8_MAXIM_TABLE[256]={
    2. 0x00,0x31,0x62,0x53,0xc4,0xf5,0xa6,0x97,
    3. 0xb9,0x88,0xdb,0xea,0x7d,0x4c,0x1f,0x2e,
    4. 0x43,0x72,0x21,0x10,0x87,0xb6,0xe5,0xd4,
    5. 0xfa,0xcb,0x98,0xa9,0x3e,0x0f,0x5c,0x6d,
    6. 0x86,0xb7,0xe4,0xd5,0x42,0x73,0x20,0x11,
    7. 0x3f,0x0e,0x5d,0x6c,0xfb,0xca,0x99,0xa8,
    8. 0xc5,0xf4,0xa7,0x96,0x01,0x30,0x63,0x52,
    9. 0x7c,0x4d,0x1e,0x2f,0xb8,0x89,0xda,0xeb,
    10. 0x3d,0x0c,0x5f,0x6e,0xf9,0xc8,0x9b,0xaa,
    11. 0x84,0xb5,0xe6,0xd7,0x40,0x71,0x22,0x13,
    12. 0x7e,0x4f,0x1c,0x2d,0xba,0x8b,0xd8,0xe9,
    13. 0xc7,0xf6,0xa5,0x94,0x03,0x32,0x61,0x50,
    14. 0xbb,0x8a,0xd9,0xe8,0x7f,0x4e,0x1d,0x2c,
    15. 0x02,0x33,0x60,0x51,0xc6,0xf7,0xa4,0x95,
    16. 0xf8,0xc9,0x9a,0xab,0x3c,0x0d,0x5e,0x6f,
    17. 0x41,0x70,0x23,0x12,0x85,0xb4,0xe7,0xd6,
    18. 0x7a,0x4b,0x18,0x29,0xbe,0x8f,0xdc,0xed,
    19. 0xc3,0xf2,0xa1,0x90,0x07,0x36,0x65,0x54,
    20. 0x39,0x08,0x5b,0x6a,0xfd,0xcc,0x9f,0xae,
    21. 0x80,0xb1,0xe2,0xd3,0x44,0x75,0x26,0x17,
    22. 0xfc,0xcd,0x9e,0xaf,0x38,0x09,0x5a,0x6b,
    23. 0x45,0x74,0x27,0x16,0x81,0xb0,0xe3,0xd2,
    24. 0xbf,0x8e,0xdd,0xec,0x7b,0x4a,0x19,0x28,
    25. 0x06,0x37,0x64,0x55,0xc2,0xf3,0xa0,0x91,
    26. 0x47,0x76,0x25,0x14,0x83,0xb2,0xe1,0xd0,
    27. 0xfe,0xcf,0x9c,0xad,0x3a,0x0b,0x58,0x69,
    28. 0x04,0x35,0x66,0x57,0xc0,0xf1,0xa2,0x93,
    29. 0xbd,0x8c,0xdf,0xee,0x79,0x48,0x1b,0x2a,
    30. 0xc1,0xf0,0xa3,0x92,0x05,0x34,0x67,0x56,
    31. 0x78,0x49,0x1a,0x2b,0xbc,0x8d,0xde,0xef,
    32. 0x82,0xb3,0xe0,0xd1,0x46,0x77,0x24,0x15,
    33. 0x3b,0x0a,0x59,0x68,0xff,0xce,0x9d,0xac
    34. };

    现在就可以开始用查表法进行计算了,代码如下:

    1. #include <stdio.h>
    2. unsigned char crc8_maxim(unsigned char *puchMsg, unsigned int usDataLen)
    3. {
    4. unsigned char uchCRC = 0xFF ;
    5. unsigned int i=0;
    6. while (usDataLen--) /* 传输消息缓冲区 */
    7. // for(i=0;i<usDataLen;i++)
    8. {
    9. uchCRC = CRC8_MAXIM_TABLE[uchCRC^*puchMsg++];
    10. }
    11. return uchCRC ;
    12. }
    13. /*使用示例*/
    14. int main(void)
    15. {
    16. unsigned char cs[2]={0xbe,0xef};
    17. printf("crc=%x\n",crc8_maxim(&cs[0],2));
    18. return 0;
    19. }

    总结

         CRC的计算法和查表法各有各的优点,查表法的时间复杂度要低,占用内存空间较大,适合于大的数据段计算,计算法会比较耗时,占用空间很小,数据越长所需要的时间就越长,适合于小的数据段计算。

  • 相关阅读:
    基于Arrow的轻量线程池
    《算法通关村第一关——链表青铜挑战笔记》
    云原生|kubernetes 你真的学废了吗---实战k8s 一(jsonpath实战)
    SQL实现自定义排序
    encodeURIComponent对url参数进行编码
    Android PackageManager 基本使用
    elementui中table嵌套input并且当input输入一个数值后,其他input中的值根据计算公式相应改变
    想做WMS仓库管理系统,找了好久才找到云表
    nodejS+vue网上招聘系统
    2022第五空间-web部分wp+复盘总结
  • 原文地址:https://blog.csdn.net/Miao8miao/article/details/139613108