Modbus协议中CRC校验和LRC校验.docx
- 文档编号:25022191
- 上传时间:2023-06-03
- 格式:DOCX
- 页数:10
- 大小:35.45KB
Modbus协议中CRC校验和LRC校验.docx
《Modbus协议中CRC校验和LRC校验.docx》由会员分享,可在线阅读,更多相关《Modbus协议中CRC校验和LRC校验.docx(10页珍藏版)》请在冰豆网上搜索。
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)));/*返回二进制补码*/ }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Modbus 协议 CRC 校验 LRC