Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Probleme mit CRC CCITT Prüfsumme (https://www.delphipraxis.net/160938-probleme-mit-crc-ccitt-pruefsumme.html)

willyxv 8. Jun 2011 20:03

Probleme mit CRC CCITT Prüfsumme
 
Hallo,

ich möchte gerne folgenden Code von C ind Delphi übersetzen.

folgender Code soll in Delphi übersetzt werden.
Code:
typedef unsigned short TDS_CRC;
#define CRC_START_VAL ((TDS_CRC)-1)
#define CRC_TAB_SIZE  256 

TDS_CRC tGetBlockCrc(UINT8 * pBlockStart, UINT32 u32Length)
{
TDS_CRC tds_crc=CRC_START_VAL;
        while (0 < u32Length--)
        {
                tds_crc = dscrcbyte(tds_crc, *pBlockStart++);
        }
        return tds_crc;
}

#define dscrcbyte( Old_crc_us, New_dat_uc) \
                        (\
                          (\
                                        (TDS_CRC) (New_dat_uc ^ ((Old_crc_us & 0x00ff) << 8))\
                                )\
                                ^ \
                                (\
                                        (TDS_CRC) (Crc_tab[(Old_crc_us >> 8)])\
                                )\
                        )

const TDS_CRC Crc_tab[CRC_TAB_SIZE] ={//the table containing (0x1021) Generatorpolynom
        0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129,
        0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252,
        0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c,
        0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
        0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672,
        0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
        0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861,
        0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
        0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
        0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5,
        0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b,
        0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
        0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9,
        0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3,
        0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c,
        0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
        0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3,
        0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
        0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676,
        0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
        0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c,
        0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16,
        0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b,
        0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
        0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36,
        0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
Da ich leider keine Ahnung von C habe, hab ich mir einen Delphi Code also Vorlage gesucht welcher mir die CRC16 Prüfsumme berechnet.

Delphi-Quellcode:
Const Crc16Tab : Array[0..255] of Word = (
$0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
$8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef,
$1231, $0210, $3273, $2252, $52b5, $4294, $72f7, $62d6,
$9339, $8318, $b37b, $a35a, $d3bd, $c39c, $f3ff, $e3de,
$2462, $3443, $0420, $1401, $64e6, $74c7, $44a4, $5485,
$a56a, $b54b, $8528, $9509, $e5ee, $f5cf, $c5ac, $d58d,
$3653, $2672, $1611, $0630, $76d7, $66f6, $5695, $46b4,
$b75b, $a77a, $9719, $8738, $f7df, $e7fe, $d79d, $c7bc,
$48c4, $58e5, $6886, $78a7, $0840, $1861, $2802, $3823,
$c9cc, $d9ed, $e98e, $f9af, $8948, $9969, $a90a, $b92b,
$5af5, $4ad4, $7ab7, $6a96, $1a71, $0a50, $3a33, $2a12,
$dbfd, $cbdc, $fbbf, $eb9e, $9b79, $8b58, $bb3b, $ab1a,
$6ca6, $7c87, $4ce4, $5cc5, $2c22, $3c03, $0c60, $1c41,
$edae, $fd8f, $cdec, $ddcd, $ad2a, $bd0b, $8d68, $9d49,
$7e97, $6eb6, $5ed5, $4ef4, $3e13, $2e32, $1e51, $0e70,
$ff9f, $efbe, $dfdd, $cffc, $bf1b, $af3a, $9f59, $8f78,
$9188, $81a9, $b1ca, $a1eb, $d10c, $c12d, $f14e, $e16f,
$1080, $00a1, $30c2, $20e3, $5004, $4025, $7046, $6067,
$83b9, $9398, $a3fb, $b3da, $c33d, $d31c, $e37f, $f35e,
$02b1, $1290, $22f3, $32d2, $4235, $5214, $6277, $7256,
$b5ea, $a5cb, $95a8, $8589, $f56e, $e54f, $d52c, $c50d,
$34e2, $24c3, $14a0, $0481, $7466, $6447, $5424, $4405,
$a7db, $b7fa, $8799, $97b8, $e75f, $f77e, $c71d, $d73c,
$26d3, $36f2, $0691, $16b0, $6657, $7676, $4615, $5634,
$d94c, $c96d, $f90e, $e92f, $99c8, $89e9, $b98a, $a9ab,
$5844, $4865, $7806, $6827, $18c0, $08e1, $3882, $28a3,
$cb7d, $db5c, $eb3f, $fb1e, $8bf9, $9bd8, $abbb, $bb9a,
$4a75, $5a54, $6a37, $7a16, $0af1, $1ad0, $2ab3, $3a92,
$fd2e, $ed0f, $dd6c, $cd4d, $bdaa, $ad8b, $9de8, $8dc9,
$7c26, $6c07, $5c64, $4c45, $3ca2, $2c83, $1ce0, $0cc1,
$ef1f, $ff3e, $cf5d, $df7c, $af9b, $bfba, $8fd9, $9ff8,
$6e17, $7e36, $4e55, $5e74, $2e93, $3eb2, $0ed1, $1ef0
);

Function TForm3.GenerateCRC16(Var s1:String):Word;
Var crc16:Word; i:Integer;
Begin
  crc16 := 0;
  For i := 1 to Length(s1) do Begin
    Crc16 := Crc16Tab[((Crc16 shr 8 ) xor Ord(s1[i])) and $ff] xor ((Crc16 shl 8) and $FFFF);
  End;
  Result := crc16;
End;

Procedure TForm3.Button1Click(Sender: TObject);
Var crc16:Word; s1:String;
Begin
  s1 := '274545957911547';

    crc16 := GenerateCRC16(s1);
    Memo1.Lines.Add(IntTostr(crc16));

End;
Leider kommt hier eine völlig andere Prüfsumme raus.

Weiß jemand wo der fehler liegt? Oder kann man diesen Delphi Code überhaupt nicht für die berechnung verwenden?

MfG Willy

sx2008 8. Jun 2011 20:30

AW: Probleme mit CRC CCITT Prüfsumme
 
Ändere mal die Deklaration deiner Funktion wie folgt:
Delphi-Quellcode:
// AnsiString (8 Byte pro Zeichen)
Function GenerateCRC16(const s1:AnsiString):Word;
Ich habe auch den Namen der Klasse TForm1 weggelassen, denn es handelt sich ja
um eine ganz gewöhnliche Funktion, die unabhängig vom Formular ist.

gammatester 8. Jun 2011 23:04

AW: Probleme mit CRC CCITT Prüfsumme
 
Neben der Ansistring-Problematik: Für (New_dat_uc ^ ((Old_crc_us & 0x00ff) << 8)) ^ Crc_tab[(Old_crc_us >> 8)] gilt:

Old_crc_us entspricht CRC16, New_dat_uc entspricht (ord(s[i]) and $FF), also muß der Delphicode doch wohl eher wie folgt aussehen:

Delphi-Quellcode:
CRC16 := ((ord(s[i]) and $FF) xor ((CRC16 and $FF) shl 8)) xor Crc16Tab[CRC16 shr 8];
Wie man leicht sieht, ist der Tabellenindex nur CRC16 shr 8 (ein and $FF kann man sich sparen, da CRC16 ein word ist). Außerdem ist es immer hilfreich, wenn man einige komplette Testbeispiele angibt.

Edit: Ausgeschlafen sehe ich gerade, daß der C-Code auch den Initalwert -1 also in Delphi CRC16 := $FFFF; benutzt.

Deep-Sea 9. Jun 2011 07:56

AW: Probleme mit CRC CCITT Prüfsumme
 
  1. Wieso muss man ausgerechnet genau diese C-Implementation übersetzen? Es gibt doch schon hunderte CRC-Funktionen die bereits in Delphi vorliegen. Da kann man sich den Stress sparen.
  2. Wieso wird ein Byte-Pointer zu einem String übersetzt? :stupid:

gammatester 9. Jun 2011 08:09

AW: Probleme mit CRC CCITT Prüfsumme
 
Zitat:

Zitat von Deep-Sea (Beitrag 1105383)
  1. Wieso muss man ausgerechnet genau diese C-Implementation übersetzen? Es gibt doch schon hunderte CRC-Funktionen die bereits in Delphi vorliegen. Da kann man sich den Stress sparen.
  2. Wieso wird ein Byte-Pointer zu einem String übersetzt? :stupid:

Die Antwort auf die erste Frage ist doch ganz einfach: Der C-Code benutzt einen speziellen Algorithmus, der mit Pascal reproduziert werden soll. Da kann man doch nicht einfach einen beliebigen anderen nehmen.

Eine Antwort auch die zweite Frage suche ich auch schon seit Jahren, ich benutze immer array of byte oder einfach pByte etc. CRC oder Hash auf Delphi-Strings anzuwenden ist wahrscheinlich nur psychologisch zu erklären [Fast alles wird mit Strings gemacht; Strings werden neuerdings auch inkrementiert, und wenn man endlich 64-Bit-Stringlängen hat, kann man große Teile des Internets in einen String laden und durchsuchen :)]

Deep-Sea 9. Jun 2011 08:27

AW: Probleme mit CRC CCITT Prüfsumme
 
Zitat:

Zitat von gammatester (Beitrag 1105389)
Der C-Code benutzt einen speziellen Algorithmus [...]

Stimmt - gerade gesehen. Dann ist das aber auch kein echtes CRC. Naja, okay.

willyxv 9. Jun 2011 09:23

AW: Probleme mit CRC CCITT Prüfsumme
 
Danke für die schnellen Antworten, aber erst mal zum Hintergrund.

Die Prüfsumme wird für die Ansteuerung eines Analysegeräts benötigt. Bis dato wurde dies von einer alten Software zuverlässig erledigt doch leider wurde nun eine Firmwareupdate durchgeführt und das alte Programm ist nun nicht mehr in der Lage sich mit dem Gerät zu Verbinden.
Um nun wieder die Ansteuerung zu ermöglichen, möchte ich ein neues Programm schreiben und da ich C nicht behersche, tue ich dies mit Delphi. Es klappt auch alles so weit so gut bis auf die Prüfsumme, das Gerät schickt mir als Antwort "ungültige Prüfsumme".

Die Berechnung der Prüfsumme habe ich so mit dem Beispiel aus der Anleitung entnommen. Leider sind hier nur zwei Zahlenbeispiele sowie der C Code (siehe oben) aufgeführt.
Beispiel 1: Wert: "274545957911547" Prüfsumme: "11547"
Beispiel 2: Wert: "385183474" Prüfsumme: "45942"

Ich habe nun verschiedene Variatnten Versucht mit dem Wert "274545957911547":

Variante 1:
Delphi-Quellcode:
Function TForm3.GenerateCRC16(Var s1:AnsiString):Word;
Var crc16:Word; i:Integer;
Begin
  crc16 := $FFFF;
  For i := 0 to Length(s1) do Begin
    CRC16 := (((Ord(s1[i])) xor ((Crc16 and $00FF) shl 8))) xor Crc16Tab[Crc16 shr 8];
  End;
  Result := crc16;
End;
Ergebniss: 4439


Variante 2:
Delphi-Quellcode:
Function TForm3.GenerateCRC16(Var s1:AnsiString):Word;
Var crc16:Word; i:Integer;
Begin
  crc16 := $FFFF;
  For i := 0 to Length(s1) do Begin
    CRC16 := (((Ord(s1[i]) and $00FF) xor ((Crc16 and $00FF) shl 8))) xor Crc16Tab[Crc16 shr 8];
  End;
  Result := crc16;
End;
Ergebniss: 4439

Variante 3:
Delphi-Quellcode:
Function TForm3.GenerateCRC16(Var s1:AnsiString):Word;
Var crc16:Word; i:Integer;
Begin
  crc16 := $FFFF;
  For i := 0 to Length(s1) do Begin
    CRC16 := (((Ord(s1[i])) xor ((Crc16) shl 8))) xor Crc16Tab[Crc16 and $FF shr 8];
  End;
  Result := crc16;
End;
Ergebniss: 13367


ich habe noch verschiedene andere Varianten versucht leider führte keine zu meinem erwünschten Ergebniss.

MfG Willy

Klaus01 9. Jun 2011 09:34

AW: Probleme mit CRC CCITT Prüfsumme
 
Guten Morgen,

sollte die Abfrage der Zeichenkette (AnsiString) nicht bei 1 anfangen?
Auf der Position 0 sind doch die Längenangaben abgelegt.

Delphi-Quellcode:
For i := 1 to Length(s1) do Begin
Grüße
Klaus

Deep-Sea 9. Jun 2011 09:48

AW: Probleme mit CRC CCITT Prüfsumme
 
Noch mal als "einfach lesbare" Version (wobei CRC16_TABLE halt die bekannte Tabelle darstellt). So entspricht es meiner Meinung nach dem C-Code. Funktioniert aber trotzdem nicht, wenn man die Beispiele berechnet.
Delphi-Quellcode:
function GenerateCRC16(const AValue: AnsiString): Word;
var
  LChar: AnsiChar;
begin
  Result := High(Result);
  For LChar in AValue do
    Result := Ord(LChar) xor (Result shl 8) xor CRC16_TABLE[Result shr 8];
end;
Sicher, dass die Beispiele Strings darstellen? :?

willyxv 9. Jun 2011 10:08

AW: Probleme mit CRC CCITT Prüfsumme
 
Zitat:

Zitat von Deep-Sea (Beitrag 1105416)
Sicher, dass die Beispiele Strings darstellen? :?

Denke schon, im Programm wird die Prüfsumme auch aus dem Namen der zu bestimmenden Werte gebildet.

Beispiel: Prüfsumme aus: "MustermannMax01011980pid006342KaliumCalciumHbLact atGlucose"


Zitat:

Zitat von Deep-Sea (Beitrag 1105416)
Delphi-Quellcode:
function GenerateCRC16(const AValue: AnsiString): Word;
var
  LChar: AnsiChar;
begin
  Result := High(Result);
  For LChar in AValue do
    Result := Ord(LChar) xor (Result shl 8) xor CRC16_TABLE[Result shr 8];
end;



Wo finde bzw setzte ich hier den Start_Val aus dem C programm?
Code:
#define CRC_START_VAL ((TDS_CRC)-1)


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:45 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz