Modbus CRC校验程序

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

Modbus CRC校验程序

基本在网上对于MODBUS 的CRC校验程序都能找到两个版本,一个是直接运算的,一个是查表法的。首先来看一下直接运算的算法运算步骤如下:步驟1:令16-bit 寄存器(CRC 暫存器) = FFFFH.

步驟2:Exclusive OR 第一個8-bit byte 的訊息指令與低位元16-bit CRC 寄存器, 做Exclusive OR ,將結果存入CRC 寄存器內。

步驟3:又移一位CRC 寄存器,將0 填入高位處。

步驟4:檢查右移的值,如果是0, 將步驟3 的新值存入CRC 寄存器內, 否則ExclusiveOR A001H 與CRC 寄存器,將結果存入CRC 寄存器內。

步驟5:重複步驟3~步驟4,將8-bit 全部運算完成。

步驟6:重複步驟2~步驟5,取下一個8-bit 的訊息指令,直到所有訊息指令運算完成。

最後,得到的CRC 寄存器的值,即是CRC 的檢查碼。值得注意的是CRC 的檢查碼必須交換放置於訊息指令的檢查碼中。网上能找到的基本代码如下[cpp] view plaincopyprint?uint16 CRC16_Check(uint8

*Pushdata,uint8 length) { uint16 Reg_CRC=0xffff; uint8 Temp_reg=0x00; uint8 i,j; for( i = 0;

i<length; i ++) { Reg_CRC^= *Pushdata++;

for (j = 0; j<8; j++) { if (Reg_CRC &

0x0001) Reg_CRC=Reg_CRC>>1^0xA001; else Reg_CRC >>=1; } } return (Reg_CRC); } 基本算法是这个意思来着的,但答案其实是错的,校验没错为何说错呢,这里程序中的少了一句:值得注意的是CRC 的檢查碼必須交換放置於訊息指令的檢查碼中意思就是高字节地位输出,低字节高位输出。翻阅GOOGLE、百度,发现什么样式的都有,直接高字节高位输出的有,高字节低位输出的也有。究竟哪个才是对的呢,经翻阅《GBT19582.1-2008基于Modbus协议的工业自动化网络规范第二部》中规范中crc 占2个字节,低字节在数据流的倒数第二个字节,而高字节在数据流最末端,即应正了高字节低位输出的做法修改程序应该如下的才是正确:如今那么多错误程序真是误人子弟啊~ 真的要用人家的程序拿来也要阅读几次了解了才能用,不然那错的都不知道了[cpp] view plaincopyprint?uint16 CRC16_Check(uint8

*Pushdata,uint8 length) { uint16 Reg_CRC=0xffff; uint8 Temp_reg=0x00; uint8 i,j; for( i = 0; i<length;

i ++) { Reg_CRC^= *Pushdata++; for (j = 0; j<8; j++) { if (Reg_CRC & 0x0001) Reg_CRC=Reg_CRC>>1^0xA001; else

Reg_CRC >>=1; } }

Temp_reg=Reg_CRC>>8; return

(Reg_CRC<<8|Temp_reg); }

/***************************************************************** ****************************************************************** ***********************************************/下面的就是查表法来计算的,原理是根据生成多项式有唯一解的方法,先把所有值算出来放在数字所在位置,然后直接带入后面位运算即可,下次再详谈这个算法思路这个代码的好处就是占用运算时间少,对于实时性高的要求下,运算步骤要比直接计算法快得多,占用的内存资源也少很多,所以如果使用还是建议使用查表法来做程序,效果的优劣很明晰。贴代码,代码可以直接使用:[cpp] view plaincopyprint?uint16

CRC16(uint8 *Pushdata,uint8 length) { uint8 uchCRCHi=0xFF; uint8 uchCRCLo=0xFF; uint8 uIndex; while(length--) { uIndex=uchCRCHi^*Pushdata++; uchCRCHi=uchCRCLo^auchCRCHi[uIndex];

uchCRCLo=auchCRCLo[uIndex]; } return (uchCRCHi<<8|uchCRCLo); } //以下是计算好的数

组表:/* CRC 高位字节值表CRC high byte */ const uint8 code auchCRCHi[] = { 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,

相关文档
最新文档