德尔福CRC16 ModbusRTU

时间:2018-08-03 01:26:15

标签: delphi crc modbus

大家好。我正在尝试创建一个将Modbus设备与我的软件通信的软件。我在CRC16上遇到问题,有时设备有时无法响应。

以下详细信息:

function CRC16(Data: AnsiString): AnsiString;
var
 i,j,iSum,f : Integer;
begin
 iSum := $FFFF;
 for i := 1 to Length(Data) do
 begin
  iSum := iSum xor Ord(Data[i]);
  for j := 1 to 8 do
  begin
   f := iSum and $0001;
   iSum := iSum shr 1;
   if f = 1 then iSum := iSum xor $A001;
  end;
 end;
 Result := AnsiChar(Lo(iSum)) + AnsiChar(Hi(iSum));
end;

procedure TForm1.Button1Click(Sender: TObject);
Var
  YearVar : String;
  AnsiOrig : ansiString;
  Ansi : ansiString;
  Ansi2 : ansiString;

  YearConvert : Integer;
  YearUpdater : String;
  YearUpdaterCRC : String;

begin
  CloseAllConnection;
  ComPortUpdate.Open;

  if ComPortUpdate.Connected then
  Begin
    YearConvert := StrToInt(Edit1.Text);

    AnsiOrig := IntToHex(YearConvert,4);
    Ansi := Copy(AnsiOrig,1,2);
    Ansi2 := Copy(AnsiOrig,3,2);

    {ShowMessage(AnsiOrig);
    ShowMessage(Ansi);
    ShowMessage(Ansi2);  }

    YearUpdater :=  chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02)+
     chr($04) +  chr(StrtoInt('$' + Ansi)) + chr(StrtoInt('$' + Ansi2));

     YearUpdaterCrc := CRC16(YearUpdater);

     //ShowMessage(StringToHex(YearUpdater + YearUpdaterCRC));
     ComPortUpdate.WriteStr(YearUpdater + YearUpdaterCRC);

     ComPortUpdate.ClearBuffer(True,True);
  End
  else
  begin
    ShowMessage('Communication port is not connected');
  end;
end;

这有效:

YearUpdater := chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02) + chr($04) +
               chr($07) + chr($E0);

但这不起作用:

YearUpdater := chr(StrToInt('$' + EditAddress.Text)) + chr($06) + chr($02) + chr($04) +  
                chr($07) + chr($DF);

我认为支票号码有误。

请提供帮助,或者发布可用的CRC16功能。预先感谢。

2 个答案:

答案 0 :(得分:0)

通常,在RS232通信中,我仅使用字符串或8位字符的长度。尝试将所有变量从字符串更改为ansistring,然后使用Ansichar()代替Chr()。

要更改的行是这样的:

YearUpdater:= chr(StrToInt('$'+ EditAddress.Text))+ chr($ 06)+ chr($ 02)+      chr($ 04)+ chr(StrtoInt('$'+ Ansi))+ chr(StrtoInt('$'+ Ansi2));

YearUpdater必须是Ansistring。

答案 1 :(得分:0)

从我的角度来看,您的CRC-16功能错误。你可以试试吗?

procedure ByteCRC(Data: Byte; var CRC: Word);
var i: Byte;
begin
  for i := 1 to 8 do
  begin
    CRC := CRC shr 1;
    if (Data and $01) xor (CRC and $0001) > 0 then
      CRC := CRC xor $A001;
    Data := Data shr 1;
  end;
end;

function CRC16(Data: AnsiString): AnsiString;
var
  i: cardinal;
  CRC: Word;
begin
  CRC := 0;
  for i := 1 to length(s) do 
    ByteCRC(ord(s[i]), CRC);
  result := AnsiChar(lo(CRC)) + AnsiChar(hi(CRC));
end;