CRC-16 / MODBUS : 1)CRC寄存器初始值为 FFFF;即16个字节全为1; 2)CRC-16 / MODBUS的多项式A001H (1010 0000 0000 0001B) ‘H’表示16进制数,‘B’表示二进制数 计算步骤为: (1).预置 16 位寄存器为十六进制 FFFF(即全为 1) ,称此寄存器为 CRC 寄存器; (2).把第一个 8 位数据与 16 位 CRC 寄存器的低位相异或,把结果放于 CRC 寄 存器; (3).检测相异或后的CRC寄存器的最低位,若最低位为1:CRC寄存器先右移1位,再与多项式A001H进行异或;若为0,则CRC寄存器右移1位,无需与多项式进行异或。 (4).重复步骤 3 ,直到右移 8 次,这样整个 8 位数据全部进行了处理; (5).重复步骤 2 到步骤4,进行下一个 8 位数据的处理; (6).最后得到的 CRC 寄存器即为 CRC 码。 附参考: 数据(16进制):01 03 61 00 00 02 CRC校验:F7 DB 附C语言实现代码: #include <stdio.h> int main(void) { unsigned short tmp = 0xffff; unsigned short ret1 = 0; unsigned char buff[6] = {0}; buff[0] = 0x01; buff[1] = 0x03; buff[2] = 0x61; buff[3] = 0x00; buff[4] = 0x00; buff[5] = 0x02; for(int n = 0; n < 6; n++){/*此处的6 -- 要校验的位数为6个*/ tmp = buff[n] ^ tmp; for(int i = 0;i < 8;i++){ /*此处的8 -- 指每一个char类型又8bit,每bit都要处理*/ if(tmp & 0x01){ tmp = tmp >> 1; tmp = tmp ^ 0xa001; } else{ tmp = tmp >> 1; } } } /*CRC校验后的值*/ printf("%X\n",tmp); /*将CRC校验的高低位对换位置*/ ret1 = tmp >> 8; ret1 = ret1 | (tmp << 8); printf("ret: %X\n",ret1); return 0; } 输出结果: F7DB ret: DBF7 // 生成modbus CRC16数据 function CRC16(sSrc:shortstring):shortstring; var tmp: word; ret1: word; buff: array of byte; n:integer; i:integer; ilen:Integer; //ssrc length begin if trim(ssrc)=‘‘ then exit; tmp:= $FFFF; ret1:= 0; ssrc:= Trim(ssrc); ssrc:= StringReplace(sSrc,‘ ‘,‘‘,[rfReplaceAll]); ilen:= length(ssrc); SetLength(buff,ilen div 2); i:=1; while i<ilen do begin buff[(i-1)div 2]:= StrToInt(‘$‘+sSrc[i]+sSrc[i+1]); i:=i+2; end; for n := 0 to Length(buff)-1 do //*此处的6 -- 要校验的位数为6个*/ begin tmp:= buff[n] xor tmp; for I := 0 to 7 do //*此处的8 -- 指每一个char类型又8bit,每bit都要处理*/ begin if(tmp and $01)<>0 then begin tmp:= tmp shr 1; tmp:= tmp xor $A001; end else begin tmp:= tmp shr 1; end; end; end; ret1 := tmp shr 8; //*将CRC校验的高低位对换位置*/ ret1 := ret1 or (tmp shl 8); Result:= IntToHex(ret1,4); //返回16进制串 用 空格 分开 crc 暂定 2字节 result:= Result[1]+Result[2]+‘ ‘+Result[3]+Result[4]; end;
原文地址:https://www.cnblogs.com/tobetterlife/p/12161832.html
时间: 2024-10-18 10:10:48