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];}@天才卧龙的博客。

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