CRC16校验码(MODBUS)原理与C#源程序

合集下载

python生成crc校验生成modbus16位校验码

python生成crc校验生成modbus16位校验码

python⽣成crc校验⽣成modbus16位校验码CRC16 Modbus计算原理1. 预置 1 个 16 位的寄存器为⼗六进制FFFF(即全为 1) , 称此寄存器为 CRC寄存器。

2. 把第⼀个 8 位⼆进制数据 (通信信息帧的第⼀个字节) 与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器。

3. 把 CRC 寄存器的内容右移⼀位( 朝低位)⽤ 0 填补最⾼位, 并检查右移后的移出位。

4. 如果移出位为 0, 重复第 3 步 ( 再次右移⼀位); 如果移出位为 1, CRC 寄存器与多项式A001 ( 1010 0000 0000 0001) 进⾏异或。

5. 重复步骤 3 和步骤 4, 直到右移 8 次,这样整个8位数据全部进⾏了处理。

6. 重复步骤 2 到步骤 5, 进⾏通信信息帧下⼀个字节的处理。

7. 将该通信信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的⾼、低字节进⾏交换。

8. 最后得到的 CRC寄存器内容即为 CRC码。

python代码实现def one_byte_crc(data, crc_data):"""处理⼀个字节的crc校验环节:param data:待处理的数据:param crc_data:crc寄存器值,最初始的为0xffff:return:"""# 把第⼀个8位⼆进制数据(通信信息帧的第⼀个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器。

crc_data_tmp1 = (get_crc_low(crc_data) ^ data) + (0xff00 & crc_data)length = 8while True:# 把CRC寄存器的内容右移⼀位(朝低位)⽤0填补最⾼位,并检查右移后的移出位。

# 如果移出位为0,重复第3步(再次右移⼀位);如果移出位为1,CRC寄存器与多项式A001(1010000000000001)进⾏异或。

16位CRC算法原理及C语言实现

16位CRC算法原理及C语言实现

按字节计算CRCunsigned int cal_crc(unsigned char *ptr,unsigned char len) {unsigned int crc;unsigned char da;unsigned int crc_ta[256]={/*CRC余式表*/0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0};crc=0;while(len--!=0){da=(unsigned char)(crc/256); /*以8位二进制数的形式暂存CRC的高8位*/crc<<=8; /*左移8位,相当于CRC的低8位乘以82*/crc^=crc_ta[da^*ptr]; /*高8位和当前字节相加后再查表求CRC,再加上以前的CRC*/ptr++;}return(crc);}按半字节计算CRCunsigned cal_crc(unsigned char*ptr,unsigned char len){unsigned int crc;unsigned char da;unsigned int crc_ta[16]={/*CRC余式表*/0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,};crc=0;while(len--!=0){da=((unsigned char)(crc/256))/16; /*暂存CRC的高四位*/crc<<=4; /*CRC右移4位,相当于取CRC的低12位)* /crc^=crc_ta[da^(*ptr/16)]; /*CRC的高4位和本字节的前半字节相加后查表计算CRC,然后上上一次CRC的余数*/da=((unsigned char)(crc/256))/16; /*暂存CRC的高4位*/crc<<=4; /*CRC右移4位,相当于CRC的低12位)*/crc^=crc_ta[da^(*ptr&0x0f)]; /*CRC的高4位和本字节的后半字节相加后查表计算CRC,然后再加上上一次CRC的余数*/ ptr++;}return(crc);}按位计算CRCunsigned int cal_crc(unsigned char *ptr,unsigned char len){unsigned char i;unsigned int crc=0;while(len--!=0){for(i=0x80;i!=0;i/=2){if((crc&0x8000)!=0) /*余式CRC乘以2再求CRC*/{crc*=2;crc^=0x1021;}else crc*=2;if((*ptr&i)!=0)crc^=0x1021; /*再加上本位的CRC*/}ptr++;}return(crc);}。

nodejs crc16modbus校验计算方法

nodejs crc16modbus校验计算方法

Node.js CRC16 Modbus校验计算方法1. 引言在Modbus通信中,CRC16校验是一种常见的校验方式,用于验证通信数据的完整性和准确性。

Node.js作为一种流行的后端开发语言,提供了丰富的库和工具,可以方便地实现CRC16 Modbus校验的计算方法。

2. CRC16 Modbus校验原理CRC(Cyclic Redundancy Check)循环冗余校验是一种通过对数据进行多项式除法操作来检测传输过程中可能出现的错误的校验方法。

在Modbus通信中,使用的是CRC16(16位循环冗余校验)算法,其计算方法如下:- 初始化CRC寄存器为0xFFFF- 对每一个字节进行如下操作:- CRC = CRC XOR 字节- 循环8次:- 如果(CRC AND 1) = 1,则CRC = (CRC >> 1) XOR 0xA001- 否则,CRC = CRC >> 1- 最终CRC即为校验结果3. Node.js实现CRC16 Modbus校验计算方法在Node.js中,可以使用Buffer类和位运算符来实现CRC16 Modbus校验的计算方法。

以下是一个简单的实现示例:```javascriptfunction crc16Modbus(buffer) {let crc = 0xFFFF;for (let i = 0; i < buffer.length; i++) {crc = (crc ^ buffer[i]) & 0xFF;for (let j = 0; j < 8; j++) {if (crc & 0x01) {crc = (crc >> 1) ^ 0xA001;} else {crc = crc >> 1;}}}return crc;}```4. 使用示例可以将上述代码保存为一个js文件,然后在Node.js环境中引入该文件,并调用crc16Modbus函数来计算需要校验的数据的CRC16值。

Modbus+RTU协议中字节型CRC-16算法详解

Modbus+RTU协议中字节型CRC-16算法详解
为了能够在计算机上实现CRC校验码的计算,需要进行如下的设定,G(x)的位数r+1=8*p+1,即G(x)的阶数为r = 8*p;信息码K(x)的位数k=8*q,信息码位数不足最高位补0。pq为正整数。
设M(x)=K(x) *xr,即M(x)的位数k+r=8*(q+p)=8*m,即m个字节(Byte)。
将余数的首位0去除,在余数的末尾后添加1位0r-6,形成新的被除数,继续与除数(1gr-1⋯g0)进行mod2运算,如此重复8次,直至m0位与除数的首位1进行异或运算,这时剩下的余数去除首位0后就是信息m7⋯m0的CRC议,常规485通讯的信息发送形式如下:
为什么新信息码与生成多项式G(x)进行模-2(mod 2)除法运算结果为0呢?
模-2(mod 2)运算采用无进位的二进制加法,恰好为异或⨁操作。
1与A做⨁,A值取反。
0与A做⨁,A值保持不变。
A⨁A = 0A与自身做⨁,其值为0。
CRC校验码的产生(K(x) *xr)mod2 G(x) = R(x)
G(x)为r+1位;K(x)为k位,K(x)*xr为k+r位,即xr使K(x)的多项式系数左移r位,添了r位的0;R(x)为r位,是CRC校验码。
新信息码N(x) = K(x) *xr+ R(x)因为K(x) *xr的后r位为0,所以上式等价于N(x) = K(x) *xr⨁R(x),此刻认为R(x)是k+r位,即认为R(x)的前k个系数为0。
设M100 mod2 G(x) = A1A2,M100表示3个字节,其中后两个字节为0;G(x)是17位的生成多项式;A1A2是CRC校验码,两个字节。则对于任意三个字节的数据M1M2M3,有M1M2M3mod2 G(x)= (M100⨁0M2M3) mod2 G(x) = ((M100 mod2 G(x))⨁((0M2M3mod2 G(x)) =A1A2⨁M2M3。

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘和’取值的多项式一一对应。

例如:代码对应的多项式为X6+X4+X2+X+1,而多项式为X5+X3+X2+X+1对应的代码101111 o标准CRC生成多项式如下表:名称生成多项式简记式*标准引用CRC-4 x4+x+1 3 ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8x8+x6+x4+x3+x2+x10x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI,IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP3、CRC-16校验码的使用:现选择最常用的CRC-16校验,说明它的使用方法。

根据Modbus协议,常规485通讯的信息发送形式如下:地址功能码数据信息校验码1byte 1byte nbyte 2byteCRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。

例如:信息字段代码为:1011001,校验字段为:1010。

发送方:发出的传输字段为:1 0 1 1 0 0 1 1 0 10信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,贝y 信息正确。

crc16校验查表法原理

crc16校验查表法原理

crc16校验查表法原理CRC(Cyclic Redundancy Check)是一种常用的数据校验方法,广泛应用于数据通信和存储中,以确保数据的完整性和准确性。

CRC校验可以通过查表法来实现,本文将介绍CRC16校验的查表法原理。

在CRC校验中,发送方和接收方通过一系列的计算操作来生成和校验校验码。

其中,CRC16是一种16位的循环冗余校验码,可以检测出多达2个比特的错误。

CRC16校验的查表法是一种基于查表的快速计算方法,通过预先构建一个256个元素的查表来加速校验码的计算。

我们需要准备一个256个元素的查表,每个元素都是一个16位的值。

这个查表可以通过生成多项式来计算得到,CRC16通常使用的是0x8005或0x1021这两个生成多项式。

通过对这两个多项式进行反转和左移操作,我们可以得到一个256个元素的查表。

接下来,我们需要将待校验的数据按照字节进行拆分,并将每个字节和当前的校验码进行异或运算。

异或运算是一种位运算,其运算规则是两个数对应位相同则结果为0,不同则结果为1。

通过不断地进行异或运算,将每个字节和当前的校验码进行异或,最终得到一个16位的校验码。

然后,我们可以通过查表的方式来加速校验码的计算。

对于每个字节,我们可以将它作为查表的索引,查表的结果就是一个16位的值。

然后,我们将这个值和当前的校验码进行异或运算,得到一个新的校验码。

通过不断地查表和异或运算,最终得到的校验码就是CRC16校验码。

CRC16校验的查表法相比于其他计算方法具有高效和简洁的特点。

通过预先构建查表,可以大大减少计算的时间和复杂度。

同时,查表法还可以方便地用于硬件电路的设计和实现,提高系统的性能和可扩展性。

需要注意的是,CRC16校验的查表法并不是唯一的实现方式,还可以使用其他方法来计算校验码。

而且,在实际应用中,不同的通信协议和设备可能会采用不同的CRC算法和生成多项式。

CRC16校验的查表法是一种基于查表的快速计算方法,通过预先构建一个256个元素的查表,可以加速CRC16校验码的计算。

CRC16的生成及校验原理

CRC16的生成及校验原理

CRC16的⽣成及校验原理计算CRC的过程,就是⽤⼀个特殊的“除法”,来得到余数,这个余数就是CRC。

它不是真正的算术上的除法!过程和算术除法过程⼀样,只是加减运算变成了XOR(异或)运算!算术上的除法:120÷9=13 余 3,120是被除数,9是除数,13是商,3是余数。

念作120除以9,或者9除120,或者9去除120!(除法的过程就不写了)这个除法计算机当然会做,但是做起来很⿇烦,因为减法有借位,很耗时间和指令!所以,计算CRC也是除法,但是⽤XOR来代替减法,这就简单多了!CRC的除法:120÷9=14 余 6,商、余数和算术除法不⼀定相同!!因为除法⽤的是XOR,⽽不是真正的减法。

以⼆进制这个计算过程:120 ⼆进制:1111000 、除数9 ⼆进制:1001 、商 14 ⼆进制:1110 余数6 ⼆进制:110从⾼位1111开始,每次进⾏⼀次XOR 的到的值后,去掉最⾼位加⼊下⼀位,每加⼀次进⾏⼀次XOR运算。

1111^1001--------------0110第⼀次XOR后得到0110,去掉最⾼位0,加⼊下⼀位0, 得1100 ,这样最⾼位是1,所以下个商是1 ,⽤^1001【很明显保留的位数与1001 保持⼀致】1100^1001--------------0101第⼆次XOR ,去掉最⾼位,加⼊下⼀位0,得1010 ,这样最⾼位是1,所以下个商是1 ,⽤^10011010^ 1001---------------0011第三次XOR,去掉最⾼位,加⼊下⼀位0,得0110 ,这样最⾼位是1,所以下个商是0 ,⽤^00000110^ 0000-------------0110最后⼀次XOR后得到0110,最⾼位的0可以消掉了,得到余数为110,即6注意,余数不是0110,⽽是110,因为最前⾯那个0已经被XOR后消掉了!可见,除法(XOR)的⽬的是逐步消掉最⾼位的1或0!由于过程是XOR的,所以商是没有意义的,我们不要。

c#CRC-16MODBUS校验计算方法及异或校验算法

c#CRC-16MODBUS校验计算方法及异或校验算法

c#CRC-16MODBUS校验计算⽅法及异或校验算法⼗年河东,⼗年河西,莫欺少年穷学⽆⽌境,精益求精只要是代码,如下:///<summary>///低字节在前///</summary>///<param name="pDataBytes"></param>///<returns></returns>static byte[] CRC16LH(byte[] pDataBytes){ushort crc = 0xffff;ushort polynom = 0xA001;for (int i = 0; i < pDataBytes.Length; i++){crc ^= pDataBytes[i];for (int j = 0; j < 8; j++){if ((crc & 0x01) == 0x01){crc >>= 1;crc ^= polynom;}else{crc >>= 1;}}}byte[] result = BitConverter.GetBytes(crc);return result;}///<summary>///⾼字节在前///</summary>///<param name="pDataBytes"></param>///<returns></returns>static byte[] CRC16HL(byte[] pDataBytes){ushort crc = 0xffff;ushort polynom = 0xA001;for (int i = 0; i < pDataBytes.Length; i++){crc ^= pDataBytes[i];for (int j = 0; j < 8; j++){if ((crc & 0x01) == 0x01){crc >>= 1;crc ^= polynom;}else{crc >>= 1;}}}byte[] result = BitConverter.GetBytes(crc).Reverse().ToArray() ;return result;}还有两个供⼤家验证的byte数组,如下:List<byte> llsst = new List<byte>() {0x79,0x79,0x01,0x01,0x00,0x1C,0x01,0x90,0x00,0x01,0x28,0xC3,0xC1,0x00,0xE9,0x9E,0x00,0x00,0x00,0x00,0x52,0x85,0x00,0x01,0x11,0x8E,0x15,0x02,0xD0,0x41,0x3E,0x02,0x0B var CrcLs3t22 = CRC16LH(llsst.ToArray());var CrcLs2t25 = CRC16HL(llsst.ToArray());低字节在前的结果为:83 9A⾼字节在前的结果为:9A 83异或校验算法:public static byte XOR_Check(List<byte> pbuf){int res = 0;int len = pbuf.Count;for (int i = 0; i < len; i++){res ^= pbuf[i];}return BitConverter.GetBytes(res)[0];}@天才卧龙的博客。

CRC16算法原理

CRC16算法原理

CRC算法及C实现学习体会2008-09-20 15:21:13 阅读161 评论0 字号:大中小订阅一、CRC算法原理CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。

在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。

16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以)后,再除以一个多项式,最后所得到的余数既是CRC码。

假设数据传输过程中需要发送15位的二进制信息 g=101001110100001,这串二进制码可表示为代数多项式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5 + 1,其中g中第k位的值,对应g(x)中x^k的系数。

将g(x)乘以x^m,既将g后加m个0,然后除以m阶多项式h(x),得到的(m-1)阶余项 r(x)对应的二进制码r就是CRC编码。

h(x)可以自由选择或者使用国际通行标准,一般按照h(x)的阶数m,将CRC算法称为CRC-m,比如CRC-32、CRC-64等。

国际通行标准可以参看/wiki/Cyclic_redundancy_checkg(x)和h(x)的除运算,可以通过g和h做xor(异或)运算。

比如将11001与10101做xor运算:明白了xor运算法则后,举一个例子使用CRC-8算法求101001110100001的效验码。

CRC-8标准的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1,既h是9位的二进制串111010101。

经过迭代运算后,最终得到的r是10001100,这就是CRC效验码。

通过示例,可以发现一些规律,依据这些规律调整算法:1. 每次迭代,根据gk的首位决定b,b是与gk进行运算的二进制码。

Modbus协议CRC16校验和LRC校验C语言实现

Modbus协议CRC16校验和LRC校验C语言实现

Modbus协议CRC16校验和LRC校验C语言实现Modbus协议RTU模式使用CRC16校验Modbus协议Ascii模式使用LRC校验CRC16校验C语言实现代码如下,使用2个文件crc16.c和crc16.hcrc16.c代码如下:#include"crc16.h"/* CRC16计算函数,ptr-数据指针,len-数据长度,返回值-计算出的CRC16数值*/ unsigned int GetCRC16(unsigned char *ptr, unsigned char len){unsigned int index;unsigned char crch = 0xFF; //高CRC字节unsigned char crcl = 0xFF; //低CRC字节unsigned char TabH[] = { //CRC高位字节值表0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ;unsigned char TabL[] = { //CRC低位字节值表0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;while (len--) //计算指定长度的CRC{index = crch ^ *ptr++;crch = crcl ^ TabH[index];crcl = TabL[index];}return (unsigned int)((crch<<8) | crcl);}crc16.h代码如下:#ifndef __CRC16_H#define __CRC16_H/* CRC16计算函数,ptr-数据指针,len-数据长度,返回值-计算出的CRC16数值*/ unsigned int GetCRC16(unsigned char *ptr, unsigned char len);#endif使用方法如下:假设数组为unsigned char send[8]={0x01,0x03,0x20,0x00,0x00,0x01,0x8F,0xCA};对数组进行CRC16校验计算,调用计算函数unsigned int crc;crc = GetCRC16(send, 6); //计算CRC校验值send[6] = crc >> 8; //CRC高字节把校验插回数组send[7] = crc & 0xFF; //CRC低字节把校验插回数组LRC校验C语言实现代码如下,使用2个文件lrc.c和lrc.hlrc.c代码如下:#include"lrc.h"/* LRC计算函数,ptr-数据指针,len-数据长度,返回值-计算出的LRC数值*/ unsigned char GetLRC(unsigned char *ptr, unsigned char len){signed int result1=0;unsigned char result2=0;unsigned char i=0;for(i=0;i<len;i++){result1+=*ptr++;}result1=0x100-result1;result2=(unsigned char)result1;return result2;}lrc.h代码如下:#ifndef __LRC_H#define __LRC_H/* LRC计算函数,ptr-数据指针,len-数据长度,返回值-计算出的LRC数值*/ unsigned char GetLRC(unsigned char *ptr, unsigned char len);#endif使用方法如下:假设数组为unsigned char send[7]={0x01,0x06,0x20,0x01,0x9c,0x41,0xfb};对数组进行LRC校验计算,调用计算函数unsigned char lrc;lrc = GetLRC(send, 6); //计算CRC校验值send[6] = lrc ; // 把校验插回数组。

modbus标准crc校验算法

modbus标准crc校验算法

文章标题:深入探讨Modbus标准CRC校验算法在工业自动化领域,Modbus通信协议是一种应用广泛的串行通信协议,其中的CRC校验算法对于数据完整性的验证起着至关重要的作用。

本文将围绕Modbus标准CRC校验算法展开深入探讨,以便读者能够更全面地了解该算法的原理和应用。

1. 什么是Modbus通信协议?Modbus是一种用于工业领域的通信协议,它通常用于连接各种自动化设备和控制系统,如PLC(可编程逻辑控制器)、传感器、执行器等。

Modbus协议可以通过串行通信或以太网进行数据传输,实现设备之间的数据交换和控制命令的传输。

2. CRC校验算法的作用及原理CRC(Cyclic Redundancy Check)是循环冗余校验的缩写,是一种通过对数据进行计算并附加校验值来验证数据完整性的算法。

在Modbus通信中,CRC校验算法被用于检测通信数据在传输过程中是否发生了误码或数据损坏。

Modbus标准CRC校验算法采用的是CRC-16-Modbus算法,它基于多项式计算和位操作来生成16位的校验码。

在发送端,数据帧的CRC校验码由发送设备计算并附加在数据帧的末尾;在接收端,接收设备也对接收到的数据帧进行CRC校验,来验证接收到的数据是否完整和正确。

3. Modbus标准CRC校验算法的具体计算方法Modbus标准CRC校验算法的计算方法比较复杂,需要对数据帧进行按位运算和多项式计算。

需要对每个字节的数据进行移位和异或运算,然后再进行一系列的位操作和多项式运算,最终得到16位的CRC校验码并附加在数据帧的末尾。

4. Modbus标准CRC校验算法的应用场景Modbus标准CRC校验算法广泛应用于工业自动化领域的数据通信和控制系统中。

它能够有效地验证数据传输的完整性和准确性,确保通信数据的可靠性和稳定性。

在 PLC、传感器、执行器等设备之间的数据交换和控制指令传输中,CRC校验算法能够及时发现并纠正数据错误,保障系统的正常运行。

16位CRC校验原理与算法分析

16位CRC校验原理与算法分析

16位CRC校验原理与算法分析2007-12-14 09:37这里,不讨论CRC的纠错原理以及为什么要选下面提及的生成多项式,只是针对以下的生成多项式,如何获得CRC校验码,作一个比较详细的说明。

标准CRC生成多项式如下表:名称生成多项式简记式* 标准引用CRC-4 x4+x+1 3ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8 x8+x6+x4+x3+x2+x1 0x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP生成多项式的最高位固定的1,故在简记式中忽略最高位1了,如0x1021实际是0x11021。

I、基本算法(人工笔算):以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。

假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0];数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。

发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];II、计算机算法1(比特型算法):1)将扩大后的数据流(6字节)高16位(BYTE[3]、BYTE[2])放入一个长度为16的寄存器;2)如果寄存器的首位为1,将寄存器左移1位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式异或;否则仅将寄存器左移1位(寄存器的最低位从下一个字节获得);3)重复第2步,直到数据流(6字节)全部移入寄存器;4)寄存器中的值则为CRC校验码CRC[1]、CRC[0]。

【转】crc16几种标准校验算法及c语言代码

【转】crc16几种标准校验算法及c语言代码

【转】crc16⼏种标准校验算法及c语⾔代码⼀、CRC16校验码的使⽤ 现选择最常⽤的CRC-16校验,说明它的使⽤⽅法。

根据Modbus协议,常规485通讯的信息发送形式如下: 地址功能码数据信息校验码 1byte 1byte nbyte 2byte CRC校验是前⾯⼏段数据内容的校验值,为⼀个16位数据,发送时,低8位在前,⾼8为最后。

例如:信息字段代码为: 1011001,校验字段为:1010。

发送⽅:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10 信息字段校验字段 接收⽅:使⽤相同的计算⽅法计算出信息字段的校验码,对⽐接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。

⼆、CRC16校验码计算⽅法 常⽤查表法和计算法。

计算⽅法⼀般都是: (1)、预置1个16位的寄存器值0xFFFF,称此寄存器为CRC寄存器; (2)、把第⼀个8位⼆进制数据(既通讯信息帧的第⼀个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器,⾼⼋位数据不变; (3)、把CRC寄存器的内容右移⼀位(朝⾼位)⽤0填补最⾼位,并检查右移后的移出位; (4)、如果移出位为0:重复第3步(再次右移⼀位);如果移出位为1,CRC寄存器与⼀多 项式(A001)进⾏异或; (5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进⾏了处理; (6)、重复步骤2到步骤5,进⾏通讯信息帧下⼀个字节的处理; (7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的⾼、低 字节进⾏交换; (8)、最后得到的CRC寄存器内容即为:CRC码。

以上计算步骤中的多项式A001是8005按位颠倒后的结果。

查表法是将移位异或的计算结果做成了⼀个表,就是将0~256放⼊⼀个长度为16位的寄存器中的低⼋位,⾼⼋位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到⼋位全部移出,最后寄存器中的值就是表格中的数据,⾼⼋位、低⼋位分别单独⼀个表。

CRC-16的原理和实现

CRC-16的原理和实现

CRC-16的原理和实现CRC的全称为Cyclic Redundancy Check,中⽂名称为循环冗余校验。

它是⼀类重要的线性分组码,编码和解码⽅法简单,检错和纠错能⼒强,在通信领域⼴泛地⽤于实现差错控制。

实际上,除数据通信外,CRC在其它很多领域也是⼤有⽤武之地的。

例如我们读软盘上的⽂件,以及解压⼀个ZIP⽂件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储⽅⾯的应⽤可略见⼀斑。

差错控制理论是在代数理论基础上建⽴起来的。

这⾥我们着眼于介绍CRC的算法与实现,对原理只能捎带说明⼀下。

若需要进⼀步了解线性码、分组码、循环码、纠错编码等⽅⾯的原理,可以阅读有关资料。

利⽤CRC进⾏检错的过程可简单描述为:在发送端根据要传送的k位⼆进制码序列,以⼀定的规则产⽣⼀个校验⽤的r位监督码(CRC码),附在原始信息后边,构成⼀个新的⼆进制码序列数共k+r位,然后发送出去。

在接收端,根据信息码和CRC码之间所遵循的规则进⾏检验,以确定传送中是否出错。

这个规则,在差错控制理论中称为“⽣成多项式”。

1 代数学的⼀般性算法在代数编码理论中,将⼀个码组表⽰为⼀个多项式,码组中各码元当作多项式的系数。

例如 1100101 表⽰为1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。

设编码前的原始信息多项式为P(x),P(x)的最⾼幂次加1等于k;⽣成多项式为G(x),G(x)的最⾼幂次等于r;CRC多项式为R(x);编码后的带CRC的信息多项式为T(x)。

发送⽅编码⽅法:将P(x)乘以xr(即对应的⼆进制码序列左移r位),再除以G(x),所得余式即为R(x)。

⽤公式表⽰为T(x)=x r P(x)+R(x)接收⽅解码⽅法:将T(x)除以G(x),如果余数为0,则说明传输中⽆错误发⽣,否则说明传输有误。

举例来说,设信息码为1100,⽣成多项式为1011,即P(x)=x3+x2,G(x)=x3+x+1,计算CRC的过程为x r P(x) x3(x3+x2) x6+x5 x-------- = ---------- = -------- = (x3+x2+x) + --------G(x) x3+x+1 x3+x+1 x3+x+1即 R(x)=x。

crc16校验原理

crc16校验原理

不难看出,余式有 256 种可能的值,实际上就是 0~255 以 X16+X12+X5+1 为权得到的 CRC 码,可以通过函数 crc16l 来计算。以 1 为例。
code test[]={0x01}; crc = 0; ptr = test; crc = crc16l(ptr,1);
执行结果 crc = 1021,这就是 1 对应的余式。
图中进行 XOR 运算的位与多项式的表达相对应。 X5 代表 Bit5,X12 代表 Bit12,1 自然是代表 Bit0,X16 比较特别,是指移 位寄存器移出的数据,即图中的 DATA OUT。可以这样理解,与数据位做 XOR 运算的是上次 CRC 值的 Bit15。 根据以上说明,可以依葫芦画瓢的写出以下程序。(程序都是在 keil C 7.10 下调 试的)
typedef unsigned char uchar; typedef unsigned int uint;
code uchar crcbuff [] = { 0x00,0x00,0x00,0x00,0x06,0x0d,0xd2,0xe3};
uint crc;
// CRC 码
void main(void)
图 1,图 2 说明了 CRC 校验中 CRC 值是如何计算出来的,体现的多项式正 是 X16+X12+X5+1。 Serial Data 即是需要校验的数据。从把数据移位开始计 算,将数据位(从最低的数据位开始)逐位移入反向耦合移位寄存器(这个名词 我也不懂,觉得蛮酷的,就这样写了,嘿)。当所有数据位都这样操作后,计算 结束。此时,16 位移位寄存器中的内容就是 CRC 码。
很多资料上都写了查表法来计算,当时是怎么也没想通。其实蛮简单的。假设通 过移位处理了 8 个 bit 的数据,相当于把之前的 CRC 码的高字节(8bit)全部移 出,与一个 byte 的数据做 XOR 运算,根据运算结果来选择一个值(称为余式), 与原来的 CRC 码再做一次 XOR 运算,就可以得到新的 CRC 码。

CRC16常见几个标准的算法及C语言实现

CRC16常见几个标准的算法及C语言实现

CRC16常见⼏个标准的算法及C语⾔实现CRC16常见的标准有以下⼏种,被⽤在各个规范中,其算法原理基本⼀致,就是在数据的输⼊和输出有所差异,下边把这些标准的差异列出,并给出C语⾔的算法实现。

CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,⾼位在后,结果与0x0000异或CRC16_CCITT_FALSE:多项式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在后,⾼位在前,结果与0x0000异或CRC16_XMODEM:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在后,⾼位在前,结果与0x0000异或CRC16_X25:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,⾼位在后,结果与0xFFFF异或CRC16_MODBUS:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,⾼位在后,结果与0x0000异或CRC16_IBM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,⾼位在后,结果与0x0000异或CRC16_MAXIM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,⾼位在后,结果与0xFFFF异或CRC16_USB:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,⾼位在后,结果与0xFFFF异或多项式产⽣:如x16+x12+x5+1x16表⽰第16位为1,x5表⽰第5位为1(1 << 16) | (1 << 12) | (1 << 5) | (1) = 0x11021但是CRC16只取低16位,写成16进制数就是 0x1021CRC16的算法原理:1.根据CRC16的标准选择初值CRCIn的值。

2.将数据的第⼀个字节与CRCIn⾼8位异或。

crc16 简式

crc16 简式

crc16 简式CRC16是Cyclic Redundancy Check 16位校验码的简称。

它是一种常用的校验算法,广泛应用于通信、存储等领域中数据的完整性校验。

本文将介绍CRC16算法的原理、应用和计算方法。

一、CRC16算法原理CRC16算法是基于多项式除法的一种校验算法。

它将待校验的数据看作二进制数,通过与一个预设的生成多项式进行除法运算得到余数,该余数就是CRC16校验码。

生成多项式可以选择不同的值,一般情况下,常用的生成多项式为0x8005和0x1021。

二、CRC16算法应用1.通信中的数据校验在通信中,为了确保数据的传输准确性,常常需要使用CRC16校验码对数据进行校验。

发送方在发送数据之前,先计算数据的CRC16校验码,并将其添加到数据帧的尾部。

接收方在接收到数据之后,同样进行CRC16校验计算,并将计算出的校验码与接收到的校验码进行比较,以判断数据是否传输正确。

2.存储中的数据校验在存储介质中,为了防止数据损坏或篡改,常常需要使用CRC16校验码对数据进行校验。

在向存储介质写入数据时,可以计算数据的CRC16校验码,并将其添加到数据的尾部。

在读取数据时,同样进行CRC16校验计算,并比较计算出的校验码与读取到的校验码,以判断数据的完整性。

三、CRC16算法计算方法CRC16算法的计算方法比较简单,其具体步骤如下:1.预处理a)初始化一个16位的寄存器,初始值为0xFFFF。

b)将生成多项式的最高位移到寄存器的最低位。

2.数据处理a)从高位到低位依次处理每个数据(字节)。

b)计算数据与寄存器的异或值,并将其作为下一轮计算的新输入。

c)将寄存器向右移动一位。

3.结果反转a)反转寄存器的所有位。

4.结果异或a)将寄存器与0xFFFF做异或运算,得到最终的CRC16校验码。

四、总结CRC16是一种常用的校验算法,能够对数据进行快速有效的完整性校验。

它广泛应用于通信、存储等领域中,能够提高数据传输和存储的可靠性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档