CRC校验(模型、手算、程序编写)
一.模型
1.WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位
2.REFIN:true或false,如为true输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据,
举例如下:
以一个4字节的原始数据为例:
3.INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。 它的值为全0或者全F,当全为0时,在算法开始前对数据(这个数据是根据RefIn的值得到的)后面补上CRC位数个0后就可以进行后续计算了。当全为1时,表示在算法开始前对数据的前CRC位数(高位)先和对应位数个1进行异或(即:前CRC位数的值按位取反),再在后面补上CRC位数个0,才进行后续计算。
下面做的详细解释与计算过程
4.POLY:多项式,以16进制表示。例如:CRC-16
所以根据计算结果为0x18005,但是十六进制多项式,省略最高位1,最终结果0x8005与表格一致
5.REFOUT:当其为false输出不做处理,当Refout为True,需要对输出数据做一次整个数据的逆序处理,注意:这里做的逆序和RefIn不同,它不是按字节逆序,而是整个逆序
以CRC-32为例来说明,最后的数据为32位,当Refout为True时,翻转如下:
6.XOROUT:结果与此参数异或后得到最终的CRC值。
根据以上六个步骤我们可以进行计算,下面我们就用手算计算一边整体过程
二、手算过程
举例:0x06数据进行CRC-16/MODBUS校验
(1)CRC-16/MODBUS的REFIN为true,需要进行逆序处理
(2)CRC-16/MODBUS的INT位0xFFFF,将“1步骤”结果与0xFFFF异或处理
(3)对“2步骤结果”进行左移16位补0,如果是CRC-8就左移8位补0,以此类推
计算如下:
知道了结果下面开始进行模2除法求余数
(4)将上面结果与多项式进行计算
第一种计算方式:带高位计算即与0x18005异或处理
注:这里只异或计算右移8位而已,而方框的后面8位不计算了;是因为我们的原始数据只有0x06一个字节(我之前在这里栽跟头了,且注意,异或移动的字节是由于你原始数据有几个字节决定的)
第二种计算方式:不含高位计算即与0x8005异或处理
注:第二种计算均会判断起始位是否为1,是1右移一位再进行计算,箭头所标写
(5)因为CRC-16/MODBUS的Refout为True,对上面数据进行整体逆序
上述结果:1111 1100 0100 0010
整体逆序:0100 0010 0011 1111
(6)因为XOUT位0x0000,所以异或完还是不变,最终结果:0100 0010 0011 1111
验证如下,计算无误
下面下面再举例进行两个字节计算:0x06 0x06 进行CRC-16/MODBUS校验
这里我手算就指计算第一种,第二种就不在写了,上面已经有写了一边
看画红线处,这次校验数据是两个字节,所以我们计算的异或右移至两个字节宽度,这就与上面一个字节形成了对比,这下子大家应该都明白了
上述结果:0100 0001 0100 1000
整体逆序:0001 0010 1000 0010
注:如遇到下面最终结果位数不足,需往前补0 ,以CRC-4举例,结果位数只有两位你就往前补两个0,使之结果为4位
在线计算器:CRC(循环冗余校验)在线计算_ip33.com
三、程序演变编写
经过前两个个步骤的执行与体验,应该都有些许感悟,我们以手算母的了解其计算流程原理,那程序也是可以以此演变而来
我们以CRC-8来计算
/******************************************************************************
* Name: CRC-8 x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
*****************************************************************************/
uint8_t crc8(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )//1号
crc = (crc << 1) ^ 0x07;//2号
else
crc <<= 1;
}
}
return crc;
}
首先1号,这个判断是不是跟我们手算第二种方式一样,是都是先要判断起始位手否为1
2号,是为1 需确定左移在异或多项式,是不是跟手算流程一至
程序流程与手算流程其实是一致的,大家可以详细对比理解下
下面在举一个例子,这个例子就有些差异,大家往下看
/*****************************************************************************
* Name: CRC-8/ROHC x8+x2+x+1
* Poly: 0x07
* Init: 0xFF
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc8_rohc(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0xFF;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xE0;
else
crc = (crc >> 1);
}
}
return crc;
}
很明显上面的数值是右移而不是像我们之前手算一样是左移,且异或的多项式也与模型上的数值0x07不一样,这次异或的是0xE0
那我们再分析下,如下图手算验证,结果都是一致。原因使我们将多项式进行字节逆序处理,其实可以只管看到所有异或的数据都是相对应没有差别,在于右移与左移的不同
所以这对 Refin: True, Refout: True,我们程序就进行了上述变换转化,多项式进行逆序
上面是以CRC-8举例,如果是CRC-16呢,那么就是讲0x8005进行整体逆序就变成0xA001
完成!
后续多个CRC模型程序,大家参考明显使用,只要手算你已经知道,那么程序都是由手算演变而来,道理一样的
/******************************************************************************
* Name: CRC-4/ITU x4+x+1
* Poly: 0x03
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc4_itu(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x0C;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-5/EPC x5+x3+1
* Poly: 0x09
* Init: 0x09
* Refin: False
* Refout: False
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc5_epc(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0x48;
while(length--)
{
crc ^= *data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x48;
else
crc <<= 1;
}
}
return crc >> 3;
}
/******************************************************************************
* Name: CRC-5/ITU x5+x4+x2+1
* Poly: 0x15
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc5_itu(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x15;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-5/USB x5+x2+1
* Poly: 0x05
* Init: 0x1F
* Refin: True
* Refout: True
* Xorout: 0x1F
* Note:
*****************************************************************************/
uint8_t crc5_usb(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0x1F;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x14;
else
crc = (crc >> 1);
}
}
return crc ^ 0x1F;
}
/******************************************************************************
* Name: CRC-6/ITU x6+x+1
* Poly: 0x03
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
*****************************************************************************/
uint8_t crc6_itu(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x30;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-7/MMC x7+x3+1
* Poly: 0x09
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
* Use: MultiMediaCard,SD,ect.
*****************************************************************************/
uint8_t crc7_mmc(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x12;
else
crc <<= 1;
}
}
return crc >> 1;
}
/******************************************************************************
* Name: CRC-8 x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc8(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x07;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-8/ITU x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x55
* Alias: CRC-8/ATM
*****************************************************************************/
uint8_t crc8_itu(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x07;
else
crc <<= 1;
}
}
return crc ^ 0x55;
}
/******************************************************************************
* Name: CRC-8/ROHC x8+x2+x+1
* Poly: 0x07
* Init: 0xFF
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc8_rohc(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0xFF;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xE0;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-8/MAXIM x8+x5+x4+1
* 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
*****************************************************************************/
uint8_t crc8_maxim(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; i++)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8C;
else
crc >>= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/IBM x16+x15+x2+1
* Poly: 0x8005
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0x0000
* Alias: CRC-16,CRC-16/ARC,CRC-16/LHA
*****************************************************************************/
uint16_t crc16_ibm(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/MAXIM x16+x15+x2+1
* Poly: 0x8005
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Note:
*****************************************************************************/
uint16_t crc16_maxim(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
return ~crc; // crc^0xffff
}
/******************************************************************************
* Name: CRC-16/USB x16+x15+x2+1
* Poly: 0x8005
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Note:
*****************************************************************************/
uint16_t crc16_usb(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0xffff;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
return ~crc; // crc^0xffff
}
/******************************************************************************
* Name: CRC-16/MODBUS x16+x15+x2+1
* Poly: 0x8005
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0x0000
* Note:
*****************************************************************************/
uint16_t crc16_modbus(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0xffff; // Initial value
while(length--)
{
crc ^= *data++;
printf("%04x\n", crc);
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
printf("%04x\n", crc);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/CCITT x16+x12+x5+1
* Poly: 0x1021
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0x0000
* Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT
*****************************************************************************/
uint16_t crc16_ccitt(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/CCITT-FALSE x16+x12+x5+1
* Poly: 0x1021
* Init: 0xFFFF
* Refin: False
* Refout: False
* Xorout: 0x0000
* Note:
*****************************************************************************/
uint16_t crc16_ccitt_false(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0xffff; //Initial value
while(length--)
{
crc ^= (uint16_t)(*data++) << 8;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x8000 )
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/X25 x16+x12+x5+1
* Poly: 0x1021
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0XFFFF
* Note:
*****************************************************************************/
uint16_t crc16_x25(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0xffff;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
}
return ~crc;
}
/******************************************************************************
* Name: CRC-16/XMODEM x16+x12+x5+1
* Poly: 0x1021
* Init: 0x0000
* Refin: False
* Refout: False
* Xorout: 0x0000
* Alias: CRC-16/ZMODEM,CRC-16/ACORN
*****************************************************************************/
uint16_t crc16_xmodem(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= (uint16_t)(*data++) << 8;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x8000 )
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1
* Poly: 0x3D65
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Use: M-Bus,ect.
*****************************************************************************/
uint16_t crc16_dnp(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA6BC;
else
crc = (crc >> 1);
}
}
return ~crc;
}
/******************************************************************************
* Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
* Poly: 0x4C11DB7
* Init: 0xFFFFFFF
* Refin: True
* Refout: True
* Xorout: 0xFFFFFFF
* Alias: CRC_32/ADCCP
* Use: WinRAR,ect.
*****************************************************************************/
uint32_t crc32(uint8_t *data, uint16_t length)
{
uint8_t i;
uint32_t crc = 0xffffffff;
while(length--)
{
crc ^= *data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xEDB88320;
else
crc = (crc >> 1);
}
}
return ~crc;
}
/******************************************************************************
* Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
* Poly: 0x4C11DB7
* Init: 0xFFFFFFF
* Refin: False
* Refout: False
* Xorout: 0x0000000
*****************************************************************************/
uint32_t crc32_mpeg_2(uint8_t *data, uint16_t length)
{
uint8_t i;
uint32_t crc = 0xffffffff; // Initial value
while(length--)
{
crc ^= (uint32_t)(*data++) << 24;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x80000000 )
crc = (crc << 1) ^ 0x04C11DB7;
else
crc <<= 1;
}
}
return crc;
}
CRC校验(模型、手算、程序编写)相关推荐
- Simulink建模:CRC校验模型
本文研究CRC校验的Simulink模型及其代码生成. 文章目录 1 CRC校验 2 C代码形式 3 Matlab/Simulink建模及代码生成 3.1 Matlab Function建模 3.2 ...
- crc校验c语言程序,C语言:CRC校验
一.CRC码 CRC:Cylic Reduancy check译作汉语就是循环冗余校验码. 二.XOR XOR:逻辑运算符异或,不知道用符号怎么写,总之其运算法则是,不同为1,相同为0. 三.用XOR ...
- 编写一个字节数的rtu C语言校验程序,Modbus通信协议中CRC校验的快速C语言算法
Modbus通信协议中CRC校验的快速C语言算法 2004年第11期 福 建 电 脑 63 Modbus通信协议中CRC校验的快速C语言算法 孟开元 (西安石油大学计算机学院陕西西安710065) [ ...
- CRC校验原理及STM32 IAP在线升级程序
CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...
- 如何在html里加入验证码_如何把crc校验加入到对应的程序里?看高手怎么做
我们现在已经搞清楚了crc校验的算法,本文我就向大家具体讲解一下如何把crc校验加入到我们的程序里. 1 .crc校验使用原理 crc校验在程序中运行的原理主要可以分为以下几步. 第一步:主站发送数据 ...
- matlab实现CRC_16,关于CRC校验实现程序解释(CRC16为例)
本文本文主要说两件事,一是对于网上一些Demo的解释,借用网友思路的Demo,如有雷同纯属巧合.二是关于数据反转的问题. 在<CRC原理--为什么算出来的CRC校验码结果总不一样?>原文链 ...
- PLC中用scl语言编写算法求解modbus crc校验码
PLC中用scl语言编写算法求解modbus crc校验码 因为不是严格的modbus协议,是用的自由口通讯,传输数据里面得加上CRC校验,所以得搞个算法根据发送不同的数据生成相应的CRC校验码. 现 ...
- CRC校验实现原理以及程序实现研究
在学习mdobus过程中,曾遇到过CRC校验,之前一直不是很明白其原理,现在利用一点闲暇时间学习下. 不同别的校验方式,想弄明白CRC校验的原理以及程序实现过程还真得有点耐心,琢磨一下数学公式. 1. ...
- c# 如何编写CRC校验算法
在C#中编写CRC校验算法,可以使用以下步骤: 首先需要确定CRC校验的多项式和初始值.根据具体的需求和应用场景,选择合适的CRC多项式和初始值. 定义一个计算CRC校验值的函数,函数的输入参数为待校 ...
- C#_C#编写的CRC校验软件
C#编写的CRC校验软件,模仿"格西CRC计算器 1.0",使用查表法 1.CRC8校验主要代码 2.CRC16主要代码 3.CRC32主要代码 大端和小端的不同处理效果 大端: ...
最新文章
- 张仰彪第二排序法_C语言中的最常用的两种排序算法你知道吗?
- python查找文件夹下的文件,python 查找文件夹下所有文件 实现代码 -电脑资料
- 记一次ssh登录异常
- 编程一个最简单游戏_一个关于AI编程的游戏
- 学习笔记——XSLT转换器的使用(Xalan和Saxon) .(转)
- Java TCP 编程简介
- sql语法中 什么值需要用单引号‘’修饰?
- 机器学习(四)决策树
- RocketMQ中的Topic和JMS的queue有什么区别?
- python语言里数字包括_4.1Python语言中的数字、字符串数据类型讲解
- Session自定义存储及分布式存储
- 遥感和GEE不正式告别
- 移动前端开发与WEB前端开发有什么联系与区别?
- java applepay_ApplePay对接java后台详细代码
- UOJ220 [NOI2016] 网格 【割顶】【并查集】
- 大学计算机教师招聘试讲什么,应聘高校教师面试,试讲注意事项
- 开源项目——小Q聊天机器人V1.3
- 利用1.1.1.1进行DNS网络加速,仅需2分钟让网络更快
- Java 对象 、String 、JSON 互转
- 混响(Reverb)/空间音效(Panning)
热门文章
- 名词后面用过去分词的具体用法是怎么样的?
- 函数判断闰年:输入年份 判断此2月份的天数
- WiFi-802.11 2.4G频段 5G频段 信道频率分配表
- python画螺旋状图形教程_如何快速绘制一个“螺旋状”图形?
- c语言一个笼子里关了鸡和兔子,成年后的你是否还质疑 古人为什么把鸡和兔子关在一个笼子里...
- 快捷键,总结一些实用高效的快捷键
- 2022年搜索引擎研究报告
- java.lang.UnsupportedOperationException: Required method instantiateItem was not overridden
- Python的缩进问题unindent does not match any outer indentation level
- 计算机excel中钱的符号,在excel中输入钱的符号 excel货币符号