Modbus协议中CRC校验和LRC校验.docx

上传人:b****4 文档编号:11966664 上传时间:2023-04-16 格式:DOCX 页数:10 大小:35.43KB
下载 相关 举报
Modbus协议中CRC校验和LRC校验.docx_第1页
第1页 / 共10页
Modbus协议中CRC校验和LRC校验.docx_第2页
第2页 / 共10页
Modbus协议中CRC校验和LRC校验.docx_第3页
第3页 / 共10页
Modbus协议中CRC校验和LRC校验.docx_第4页
第4页 / 共10页
Modbus协议中CRC校验和LRC校验.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

Modbus协议中CRC校验和LRC校验.docx

《Modbus协议中CRC校验和LRC校验.docx》由会员分享,可在线阅读,更多相关《Modbus协议中CRC校验和LRC校验.docx(10页珍藏版)》请在冰豆网上搜索。

Modbus协议中CRC校验和LRC校验.docx

Modbus协议中CRC校验和LRC校验

CRC的生成

循环冗余校验(CRC)域为两个字节,包含一个二进制16位值。

附加在报文后面的CRC的值由发送设备计算。

接收设备在接收报文时重新计算CRC的值,并将计算结果于实际接收到的CRC值相比较。

如果两个值不相等,则为错误。

CRC的计算,开始对一个16位寄存器预装全1.然后将报文中的连续的8位子节对其进行后续的计算。

只有字符中的8个数据位参与生成CRC的运算,起始位,停止位和校验位不参与CRC计算。

CRC的生成过程中,每个8–位字符与寄存器中的值异或。

然后结果向最低有效位(LSB)方向移动(Shift)1位,而最高有效位(MSB)位置充零。

然后提取并检查LSB:

如果LSB为1,则寄存器中的值与一个固定的预置值异或;如果LSB为0,则不进行异或操作。

这个过程将重复直到执行完8次移位。

完成最后一次(第8次)移位及相关操作后,下一个8位字节与寄存器的当前值异或,然后又同上面描述过的一样重复8次。

当所有报文中子节都运算之后得到的寄存器中的最终值,就是CRC.

生成CRC的过程为:

1.将一个16位寄存器装入十六进制FFFF(全1).将之称作CRC寄存器.

2.将报文的第一个8位字节与16位CRC寄存器的低字节异或,结果置于CRC寄存器.

3.将CRC寄存器右移1位(向LSB方向),MSB充零.提取并检测LSB.

4.(如果LSB为0):

重复步骤3(另一次移位).(如果LSB为1):

对CRC寄存器异或多项式值0xA001(1010000000000001).

5.重复步骤3和4,直到完成8次移位。

当做完此操作后,将完成对8位字节的完整操作。

6.对报文中的下一个字节重复步骤2到5,继续此操作直至所有报文被处理完毕。

7.CRC寄存器中的最终容为CRC值.

8.当放置CRC值于报文时,如下面描述的那样,高低字节必须交换。

MODBUS协议的CRC校验子程序代码

为方便读者使用MODBUS协议,将VC、VB、ASM51环境下MODBUS协议的CRC校验子程序代码一并给出,供读者参考。

//***CRCCalculationforMODBUSProtocolforVC***//

//数组snd为地址等传输字节,num为字节数,发为6收为5//

unsignedintmb_crc(BYTE*snd,intnum)

{

inti,j;

unsignedintc,crc=0xFFFF

for(i=0;i

{

c=snd[i]&0x00FF;

crc^=c;

for(j=0,j<8,j)

{

if(crc&0x0001)

{

crc>>=1;

crc^=0xA001;

}

else

crc>>=1

}

}

return(crc);

}

unsignedshortintCrcCheck(constunsignedchar*buffer,constintbuffLen)

{

unsignedshortintcrcValue=0;

if(!

buffer||buffLen<0)

{

returncrcValue;

}

intCRCHi[]={

0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,0x0,

0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,

0x81,0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,

0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,

0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x1,

0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,

0x80,0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,

0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,

0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,

0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,

0x80,0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,

0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,

0x0,0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x1,

0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1,

0x81,0x40,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,

0x40,0x1,0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,

0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,0x81,0x40,0x1,

0xC0,0x80,0x41,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x0,0xC1,

0x81,0x40,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40,0x1,0xC0,0x80,

0x41,0x1,0xC0,0x80,0x41,0x0,0xC1,0x81,0x40

};

intCRCLo[]={

0x0,0xC0,0xC1,0x1,0xC3,0x3,0x2,0xC2,0xC6,0x6,0x7,0xC7,0x5,

0xC5,0xC4,0x4,0xCC,0xC,0xD,0xCD,0xF,0xCF,0xCE,0xE,0xA,0xCA,

0xCB,0xB,0xC9,0x9,0x8,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

};

inti,m;

intdCRCHi=0xFF;

intdCRCLo=0xFF;

for(i=0;i

{

m=dCRCLo^buffer[i];

dCRCLo=dCRCHi^CRCHi[m];

dCRCHi=CRCLo[m];

}

crcValue=dCRCLo+(dCRCHi<<8);

returncrcValue;

}

 

'//***CRCCalculationforMODBUSProtocolforVB***//

Functionmb_crc(ByRefsnd()asBYTE,numasinteger)asLong

crc_l=crc_h=&HFF

fori=1tonum

crc_l=crc_lXORsnd(i)

forj=1to8

ifcrc_lAND1then

crc_l=(crc_l-1)/2

ifcrc_hand1then

crc_l=crc_l128

crc_h=(crc_h-1)/2

endif

crc_l=crc_lXOR&HA0

crc_h=crc_hXOR&H01

else:

crc_l=crc_l/2

ifcrc_hand1then

crcl_l=crc_l128

crc_h=(crc_h-1)/2

else:

crc_h=crc_h/2

endif

endif

nextj

nexti

mb_crc=crc_lcrc_h*256

EndFunction

;CRCCalculationforMODBUSProtocolforASM51

;R1为发送(接收)字节的缓存首地址

;R2为发送(接收)字节的字节数(不含CRC字节),

;R3为CRC校验低位字节,

;R4为CRC校验高位字节,

CRC:

MOVA,#0FFH

MOVR4,A

MOVR3,A

CRC1:

MOVA,R1

XRLA,R3

MOVR3,A

MOVR2,#08H

CRC8:

CLRC

MOVA,R4

RRCA

MOVR4,A

MOVA,R3

RRCA

MOVR3,A

JNCCRC10

MOVA,R3

XRLA,#01H

MOVR3,A

MOVA,R4

XRLA,#0A0H

MOVR4,A

CRC10:

DJNZR2,CRC8

INCR1

DJNZCRC1

RET

LRC的生成

纵向冗余校验(LRC)为一个字节,含有8位二进制值。

LRC由发送设备计算,并附加LRC到报文。

接收设备在接收文时计算LRC,并将计算的结果与在LRC接收到的实际值相比较,如果两个值不相等,则结果为错。

LRC的计算,对报文中的所有的连续8位字节相加,忽略任何进位,然后求出其二进制补码。

LRC为一个8位域,那么每个会导致值大于255新的相加只是简单的将域的值在零”回绕”。

因为没有第9位,进位被自动放弃。

生成一个LRC的过程为:

1.不包括起始”冒号”和结束CRLF的报文中的所有字节相加到一个8位域,故此进位被丢弃。

2.从FF(全1)十六进制中减去域的最终值,产生1的补码(二进制反码)。

3.加1产生二进制补码.

将LRC置于报文当8位LRC(2个ASCII字符)在报文中传送时,高位字符首先发送,然后是低位字符。

例如,如果LRC值为十六进制61(01100001):

例:

下面给出了执行生成LRC的C语言函数。

函数带有两个参数:

unsignedchar*auchMsg;指向含有用于生成LRC的二进制数据报文缓冲区的指针,

unsignedshortusDataLen;报文缓冲区的字节数.

LRC生成函数

staticunsignedcharLRC(auchMsg,usDataLen)/*函数返回unsignedchar类型的LRC结果*/

unsignedchar*auchMsg;/*要计算LRC的报文*/

unsignedshortusDataLen;/*报文的字节数*/

{

unsignedcharuchLRC=0;/*LRC初始化*/

while(usDataLen--)/*完成整个报文缓冲区*/

uchLRC+=*auchMsg++;/*缓冲区字节相加,无进位*/

return((unsignedchar)(-((char)uchLRC)));/*返回二进制补码*/

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1