黄工无刷电机学习
直播中

早知

9年用户 1240经验值
擅长:光电显示 存储技术
私信 关注
[问答]

CRC16的计算校验码的方式有哪几种?

CRC16的计算校验码的方式有哪几种?

如何使用Delphi编写Modbus RTU CRC16的校验码?

回帖(1)

黄长梅

2021-11-3 09:28:19
在工业控制中,Modbus RTU CRC16的校验码用的比较广泛,包括本人富士产品中,PC与伺服电机以及PC与VP系列的变频器的Modbus RTU通讯中都使用到了CRC16.
      而对CRC16的计算的方式基本上有2种:第一种,使用双循环依照CRC的计算方法进行计算,第二种,采用查表的方式。本人愚钝无比,从网络上搜来的查表法都与实际的正确CRC16的结果有所差异,因此编写了一个小程序供自己使用。
     软件的界面很简单,输入诸如“010303020014”的值,然后每2个字符作为一个字节,填入字节数,然后就可以计算出校验码,校验码的多项式为:X16+X15+X2+1.
  
      实现的源代码如下:
     unit Unit1;
   

    interface
   

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
   

    type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        Edit2: TEdit;
        Edit3: TEdit;
        Label1: TLabel;
        Label2: TLabel;
        Label3: TLabel;
        Memo1: TMemo;
        Label4: TLabel;
      function CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
   

    var
      Form1: TForm1;
   

    implementation
   

    {$R *.dfm}
    //××××××××××××××××××××××××××
    // CalCRC16用于计算Modbus RTU的CRC16
    // 多项式公式为X16+X15+X2+1
    //××××××××××××××××××××××××××
    function TForm1.CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
    const
      GENP=$A001;  //多项式公式X16+X15+X2+1(1100 0000 0000 0101)
    var
      crc:Word;
      i:Integer;
      tmp:Byte;
    procedure CalOneByte(AByte:Byte);  //计算1个字节的校验码
    var
    j:Integer;
    begin
      crc:=crc xor AByte;   //将数据与CRC寄存器的低8位进行异或
      for j:=0 to 7 do      //对每一位进行校验
      begin
        tmp:=crc and 1;        //取出最低位
        crc:=crc shr 1;        //寄存器向右移一位
        crc:=crc and $7FFF;    //将最高位置0
        if tmp=1 then         //检测移出的位,如果为1,那么与多项式异或
          crc:=crc xor GENP;
          crc:=crc and $FFFF;
      end;
    end;
    begin
      crc:=$FFFF;             //将余数设定为FFFF
      for i:=AStart to AEnd do   //对每一个字节进行校验
        CalOneByte(AData);
      Result:=crc;
    end;
   

   

   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Data:array[0..255] of Byte;
      i,j,Count:Integer;
      Res:Word;
      szData:string;
    begin
      szData:=Form1.Edit2.Text;    //读入欲校验的字符串
      Count:=StrToInt(form1.Edit3.Text); //读入需要计算的字符串长度
      i:=1;
      j:=0;
      for j:=0 to Count-1 do
      begin
        if (i mod 2)=0 then    //每2个字符放入一个字节中
             i:=i+1;
        if i>=Length(szData) then
            exit;
        Data[j]:=StrToInt('$'+copy(szData,i,2)); //取出字符并转换为16进制数
        i:=i+1;
      end;
   

      Res:=CalCRC16(Data,Low(Data),Count-1);
      form1.Edit1.Text:=IntToHex(Res,4);
    end;
   

    end.
举报

更多回帖

发帖
×
20
完善资料,
赚取积分