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

在工业控制中,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[i]);
  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.

你可能感兴趣的:(delphi,integer,button,forms,byte,class)