一、背景

CRC计算中常用空间换时间的方案即查表法,从前面的文章关于CRC的介绍中不难知道,crc的表其实就是对于整个字节256个数据的不同结果记录的集合。

1. 本文主要针对CRC16查表法表的计算,因为crc16有多种协议,因此代码做了针对不同协议的合集,先列出各个协议之间的区别

CRC算法名称 多项式 宽度 初始值 结果异或 输入反转 输出反转
CRC16_CCITT 1021 16 0000 0000 true true
CRC16_X25 1021   16 ffff ffff true true
CRC16_MAXIM 8005 16 0000 ffff true true
CRC16_USB 8005 16 ffff ffff true true
CRC16_MODBUS 8005 16 ffff 0000 true true
CRC16_IBM 8005 16 0000 0000 true true
CRC16_DNP 3d65 16 0000 ffff true true

2.模二除法的原理

crc校验码生成的原理是数据对多项式进行模二除法求余,因此查表法表格的数据就是对一个字节的所有数据进行模二除法后的生成的校验码。其基本原理如下:

data :0x01
poly :0x1021
seed :0x01000 0000 | 0000 0000 0000 0000     //(swap(0x01) << 16u)1000 1000   0001 0000 1             //0x11021------------------1000   0001 0000 1000 01000   1000 0001 0000 1-----------------------1001 0001 1000 1000     //(0x9188)  swap后得 0x1189(swap)  0001 0001 1000 1001     //(0x1189)

swap的操作是针对这个协议CCITT要对输入的数据进行反转,具体反转的操作就是最高位和最低位的数据互换,次高位和次低位数据进行互换,具体操作可参考我的文章:(96条消息) C语言数据高低位转换(8-16-32位)_溪山行旅1024的博客-CSDN博客

使用代码的效果如下:检测高位遇到1相除并更新除数,遇到0则进行移位操作

for(i=0;i<256;i++){        for(int j=0;j<8;j++){if(p&0x8000){    p=p<<1;p = (p^poly);}else{p=p<<1;}}
}

当然此段代码只是数据已经进行过seed赋初值,输入反转之后的模二除法操作,具体的操作还需要加上对多项式poly和初始值seed的配置及最后对结果进行异或操作

将CRC16的协议类型作为参数分别获得seed和poly:

static u32 poly_seed_config(u8 poly_type)
{u32 poly_cfg = 0;switch(poly_type){case  CRC16_CCITT:poly_cfg = 0x10210000;break;case    CRC16_X25 :poly_cfg = 0x1021ffff;break;case    CRC16_MAXIM:poly_cfg = 0x80050000;break;case   CRC16_USB :poly_cfg = 0x8005ffff;break;case   CRC16_MODBUS:poly_cfg = 0x8005ffff;break;case   CRC16_IBM :poly_cfg = 0x80050000;break;case   CRC16_DNP :poly_cfg = 0x3d650000;break;default:break;}return poly_cfg ;
}void main()
{u16 poly = poly_seed_config(CRC16_IBM) >> 16u;u16 seed = (u16)poly_seed_config(CRC16_IBM) & 0xffff;
}

此外,将CRC16的协议类型作为参数获得异或操作数:

static u16 result_config(u8 poly_type)
{u16 result = 0;switch(poly_type){case  CRC16_CCITT:result = 0x0000;break;case    CRC16_X25 :result = 0xffff;break;case  CRC16_MAXIM:result = 0xffff;break;case   CRC16_USB:result = 0xffff;break;case   CRC16_MODBUS:result = 0x0000;break;case   CRC16_IBM :result = 0x0000;break;case   CRC16_DNP :result = 0xffff;break;default:break;}return result ;
}
void main(){u16 poly = poly_seed_config(CRC16_IBM) >> 16u;u16 seed = (u16)poly_seed_config(CRC16_IBM) & 0xffff;u16 xor_result = result_config(CRC16_IBM);
}

综上分析,我们只需要知道协议的类型就可以计算出0~ff数据的crc值,将他们放进一个char类型的表中,即为我们所需的CRC表 ,完整实现代码(以CRC16_IBM为例)如下:

void main()
{u16 poly = poly_seed_config(CRC16_IBM) >> 16u;u16 seed = (u16)poly_seed_config(CRC16_IBM) & 0xffff;u16 xor_result = result_config(CRC16_IBM);u16 table[256];u16 i=0;u16 p=0;for(i=0;i<256;i++){   p=i^seed;p=(u16)(crc_swap_u32((u32)p)>>16);for(int j=0;j<8;j++){if(p&0x8000){ p=p<<1;p = (p^poly);}else{p=p<<1;}}table[i]=crc_swap_u32((u32)p)>>16 ^ xor_result;printf("0x%xu, ", table[i]);if((i+1)%8 == 0)printf("\n");}}

最终计算的结果如下:

E002-CRC查表法-表的由来与实现1相关推荐

  1. CRC查表法——表的由来及Java实现CRC8校验算法

    转载请标明出处: http://blog.csdn.net/xx326664162/article/details/51718857 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定 ...

  2. 常用crc查表法_CRC校验码简介及CRC16的计算方法

    点击上方"嵌入式从0到1",选择"置顶/星标公众号" 干货福利,第一时间送达! 什么是CRC校验? CRC即循环冗余校验码(Cyclic Redundancy ...

  3. 常用crc查表法_查表法计算CRC

    (查表法)CRC检验码的计算过程 (1)将上次计算出的CRC校验码右移一个字节: (2)将移出的这个字节与新的要校验的字节进行XOR 运算: (3)用运算出的值在预先生成码表中进行索引,获取对应的值( ...

  4. 常用crc查表法_请教查表法计算CRC的原理

    自己写过的, 希望对你有帮助 Cyclic Redundancy Check(CRC) 原理及实现 /// 1: 需求 在数据传送过程中,为了能够进行错误检测, 往往在数据后追加一些检测码, 当接受方 ...

  5. CRC校验查表法原理及实现(CRC-16)

    绪论 在网上浏览了很多关于CRC校验的文章,基本上都是针对CRC校验原理的阐述以及关于CRC校验查表法的实际应用以及具体软件实现方法. 至于查的表是怎么来的,软件为什么要这样实现很多文章并没有说明.本 ...

  6. golang crc校验 crc8 crc32 查表法

    golang crc校验 crc8 crc32 查表法 package utilimport ("math" )var crc32tab = []uint32{0x00000000 ...

  7. CRC查表法运算原理

    CRC校验是依据多项式模2运算进行的,这里有两点: 1. 一个二进制串总可以表示为多项式,例如: 10101 表示为  10111 表示为 ,依次类推更长数据的表示方法. 2. 模2运算的基本规则如下 ...

  8. CRC冗余校验码及查表法

    CRC冗余校验码及查表法 什么是CRC编码 它将一个长度为k的位串看作是系数是0或者1的k-1次多项式 使用一个长度为r+1的生成多项式进行模2计算,生成一个长度为r的字符序列,能检测长度小于等于r的 ...

  9. 16 位 CRC 查表法的简单使用方法

    16位CRC查表法的简单使用方法 Modbus CRC16: crc16.h #ifndef __CRC16_H__ #define __CRC16_H__#include "main.h& ...

最新文章

  1. 服务器子系统是什么,服务器是什么样子的,服务器一般用什么系统!
  2. go怎么用改变c语言程序位置,Go与C语言的互操作
  3. python 元类的call总结_Python 类与元类的深度挖掘 I【经验】
  4. 主机数,子网数,网络号,主机号
  5. Oracle Rownum 伪列详解
  6. Hierarchical clustering
  7. 简单c语言程序例子与运行结果图,C语言程序第一次作业
  8. 利用雪碧图及css自制的动态变色导航栏
  9. 代写品牌故事四步写作方法
  10. 猫盘plus开启ssh登录
  11. 会网站seo技巧,提升流量不难
  12. VMware残留问题
  13. 基于百度图像识别api的游戏(coc)辅助工具分析
  14. 低端键盘拆解(牛屎芯片、键盘导电膜、键盘帽、橡胶垫)
  15. C++数组——小鱼比可爱
  16. SSM框架整合时applicationContext.xml文件的配置及详细解析
  17. 【图像处理】简单的车牌识别
  18. Prism:Uber 的 Presto 查询网关服务
  19. 英特尔磁盘快速存储技术-Intel RST 修复4t硬盘
  20. jQuery Api 学习(六、jQuery 文档 - 操作文档)

热门文章

  1. 一分钟搞定触手app主页酷炫滑动切换效果
  2. Linux下ion内存,Linux内核驱动:ion memory
  3. 【原创】JS+COOKIES实现健壮的购物车!
  4. 计算机安全模式的作用是什么情况,win10安全模式有什么作用
  5. 模拟美萍加密狗--Rockey2虚拟狗(二)
  6. 介绍一款密码分析软件cap4
  7. Javascript注册页面验证登录
  8. electron 打开调试_Electron教程:菜鸟学Electron 主进程调试
  9. JDBC链接数据库的步骤
  10. 黑苹果MacOS 10.13.6(High Sierra) Itunes不显示Iphone设备