AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CRC von C in Delphi übersetze

Ein Thema von ZOD · begonnen am 23. Mär 2023 · letzter Beitrag vom 28. Mär 2023
Antwort Antwort
Seite 2 von 2     12   
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#11

AW: CRC von C in Delphi übersetze

  Alt 25. Mär 2023, 14:03
Folgendes Programm liefert bei mir das korrekt Ergebnis

Delphi-Quellcode:
program CRCTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SysUtils;

function cal_crc_half(pin: PByte; len: Byte): Word;
var
  crc: Word;
  da: Byte;
  ptr: PByte;
  bCRCHign: Byte;
  bCRCLow: Byte;
const
  crc_ta: array[0..15] of Word = ($0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
                                  $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef);
begin
  ptr := pin;
  crc := 0;
  while (len > 0) do
  begin
    da := crc shr 12; // CRC high four bits
    crc := crc shl 4; // The CRC is shifted to the right by 4 bits, which is equivalent to taking the lower 12 bits of the CRC.
    crc := crc xor crc_ta[da xor (ptr^ shr 4)]; // Add the upper 4 bits of the CRC and the first half of the byte and look up the table to calculate the CRC, then add the remainder of the last CRC.
    da := crc shr 12; // CRC high four bits
    crc := crc shl 4; // The CRC is shifted to the right by 4 bits, which is equivalent to taking the lower 12 bits of the CRC.
    crc := crc xor crc_ta[da xor (ptr^ and $0f)]; // Add the upper 4 bits of the CRC and the last half of the byte and look up the table to calculate the CRC, then add the remainder of the last CRC.
    Inc(ptr);
    Dec(len);
  end;
  bCRCLow := crc and $FF;
  bCRCHign := crc shr 8;
  if (bCRCLow = $28) or (bCRCLow = $0d) or (bCRCLow = $0a) then
    Inc(bCRCLow);
  if (bCRCHign = $28) or (bCRCHign = $0d) or (bCRCHign = $0a) then
    Inc(bCRCHign);
  crc := (bCRCHign shl 8) + bCRCLow;
  Result := crc;
end;

var
  Test: AnsiString;
  CRC: Word;
begin
  try
    Test := 'QPIGS';
    CRC := cal_crc_half(Pointer(Test), Length(Test));
    writeln(IntToHex(CRC, 4));
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
472 Beiträge
 
#12

AW: CRC von C in Delphi übersetze

  Alt 26. Mär 2023, 00:10
Tipps und Hinweise sind ausdrücklich willkommen!
Wenn deine Vorgaben vollständig waren, sollte das die Lösung sein:
Delphi-Quellcode:
{$R-}
function CalcCRC(const pmcText: AnsiString): Word;
const
  CRC_TABLE: array[0..15] of Word = (
    $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
    $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef);
var
  p: PAnsiChar;
  crc: Word;
  tbl: Byte;
  crcLo: Byte;
  crcHi: Byte;
begin
  if pmcText = 'then Exit(0); //=>

  crc := 0;
  p := Pointer(pmcText);
  while p^ <> #0 do
  begin
    tbl := crc shr 12;
    crc := crc shl 4;
    crc := crc xor CRC_TABLE[tbl xor (Ord(p^) shr 4)];
    tbl := crc shr 12;
    crc := crc shl 4;
    crc := crc xor CRC_TABLE[tbl xor (Ord(p^) and $0f)];
    Inc(p);
  end;
  crcLo := crc and $ff;
  crcHi := crc shr 8;
  if (crcLo = $28) or (crcLo = $0d) or (crcLo = $0a) then
    Inc(crcLo);
  if (crcHi = $28) or (crcHi = $0d) or (crcHi = $0a) then
    Inc(crcHi);
  crc := (crcHi shl 8) + crcLo;
  Result := crc;
end;
{$R+}
Die Übersetzung ist nahe am C-Code und bestätigt die Doku:
Delphi-Quellcode:
var
  txt: AnsiString;
begin
  txt := 'QPIGS';
  ShowMessage(CalcCRC(txt).ToHexString(4)); // => $B7A9
Bis bald...
Thomas

Geändert von mytbo (26. Mär 2023 um 00:19 Uhr) Grund: Bereichsprüfung deaktiviert
  Mit Zitat antworten Zitat
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#13

AW: CRC von C in Delphi übersetze

  Alt 27. Mär 2023, 07:21
Guten Morgen!

sorry - am Freitag spät Abends war ich platt, aber ich hatte eine Lösung!

Diese Seite hat mich auf die richtige Spur gebracht:
https://www.lammertbies.nl/comm/info/crc-calculation

Es handelt sich bei meiner Aufgabe um ein CCITT XMODEM CRC. So habe ich es dann gelöst:


Delphi-Quellcode:
function CAL_CRC_CCITT_XMODEM(data: PByte; len: Integer): Word;

const
  poly = $1021;

var
  i, j: Integer;
  crc: Word;

begin
  crc := 0;
  for i := 0 to len-1 do
  begin
    crc := crc xor (Word(data^) shl 8);

    for j := 0 to 7 do
    begin
      if (crc and $8000) > 0 then
        crc := (crc shl 1) xor poly
      else
      crc := crc shl 1;
    end;
    Inc(data);
  end;
  Result := crc;
end;
Meinen ausdrücklichen Dank an alle Helfer hier!
Es ist wirklich schön zu wissen, dass man nach Hilfe fragen kann und diese auch bekommt.
Danke!

Gruß und und eine schöne Woche
Markus
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
472 Beiträge
 
#14

AW: CRC von C in Delphi übersetze

  Alt 27. Mär 2023, 21:33
sorry - am Freitag spät Abends war ich platt, aber ich hatte eine Lösung!
Bist du sicher, dass deine Lösung richtig ist?

Delphi-Quellcode:
function CAL_CRC_CCITT_XMODEM(data: PByte; len: Integer): Word;

const
  poly = $1021;

var
  i, j: Integer;
  crc: Word;

begin
  crc := 0;
  for i := 0 to len-1 do
  begin
    crc := crc xor (Word(data^) shl 8);

    for j := 0 to 7 do
    begin
      if (crc and $8000) > 0 then
        crc := (crc shl 1) xor poly
      else
      crc := crc shl 1;
    end;
    Inc(data);
  end;
  Result := crc;
end;
Deine Interpretation entspricht nicht dem C-Code aus dem ersten Post. Ein einfacher automatisierter Test über 1M Runden ergibt bei mir ca. >25K Konflikte.
Delphi-Quellcode:
{$R-}
function CalcCRC(pmPText: PAnsiChar): Word;
const
  CRC_TABLE: array[0..15] of Word = (
    $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
    $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef);
var
  idx: Byte;
  crc: WordRec absolute Result;
begin
  Result := 0;
  if pmPText = Nil then Exit; //=>

  while pmPText^ <> #0 do
  begin
    idx := (Result shr 12) xor (Ord(pmPText^) shr 4);
    Result := (Result shl 4) xor CRC_TABLE[idx];
    idx := (Result shr 12) xor (Ord(pmPText^) and $0f);
    Result := (Result shl 4) xor CRC_TABLE[idx];
    Inc(pmPText);
  end;

  if (crc.Lo = $28) or (crc.Lo = $0d) or (crc.Lo = $0a) then
    Inc(crc.Lo);

  if (crc.Hi = $28) or (crc.Hi = $0d) or (crc.Hi = $0a) then
    Inc(crc.Hi);
end;
{$R+}

var
  txt: AnsiString;
begin
  for var i: Integer := 0 to 1000000 do
  begin
    txt := TSynTestCase.RandomIdentifier(1 + Random(20));
    if CalcCRC(Pointer(txt)) <> CAL_CRC_CCITT_XMODEM(Pointer(txt), Length(txt)) then
      TSynLog.Add.Log(sllInfo, Utf8ToString(txt));
Teste deine Version mal gegen das C-Original für folgende Eingaben: YO, ZOL, DIHN, VRY77, PK20OM, 6A07EBH

Bis bald...
Thomas
  Mit Zitat antworten Zitat
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#15

AW: CRC von C in Delphi übersetze

  Alt 28. Mär 2023, 12:50
richtig, das ist NICHT der usrprünglich gepostete Code. Dieser war eine C nach Delphi Übersetzung des Codes aus der Dokumentation des Geräteherstellers.

Das Problem ist, dass die Doku schlicht falsch ist. Der richtige CRC Ansatz ist:

Zitat:
Es handelt sich bei meiner Aufgabe um ein CCITT XMODEM CRC. So habe ich es dann gelöst:
Und tatsächlich - dieser Ansatz funktioniert sowohl bei CRC für gesendete Kommandos wie bei der Kontrolle des CRC aus empfangenen Daten.

Nochmals Dank für die Mühe.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz