![]() |
CRC16 Problem mit Input ASCII/Hex
Hallo zusammen,
ich habe noch nicht so viel Erfahrung mit programmierung und daher kommt die Frage/mein Problem hier vielleicht etwas trivial vor, aber ich beise mir daran schon länger die Zähne aus. Ich soll für eine Kommunikation mit einem externen Gerät eine Checksumme mit CRC16 und dem Polynom $A001 berechnen. Den CRC habe ich bereits implementiert für eine ASCII Eingabe:
Code:
Aufrufen kann ich z.B. mit einer String Eingabe (Command):
function CalcCRC(Command: String; var Value: Int32): Integer;
var i,j : Integer; begin Result := 0; for i:=0 to Length(Command) do begin for j:=0 to 7 do begin if ((ord(Command[i]) and $01) XOR (Value And $0001) <> 0) then Value := (Value shr 1) XOR $A001 else Value := Value shr 1; ord(Command[i]) := ord(Command[i]) shr 1; end; end; end;
Code:
Das Ergebnis, was ich hier erhalten ist 0xA3DA. Dies ist auch das richtige Ergebnis, auch mit der Berechnung diverser Calculatoren (z.B.
command := '020D000A413068656C6C6F';
CalcCRC(command, crc); Result := IntToHex(crc, 4); ![]() Ich habe mir schon diverse Seiten und diverse Posts durchgelesen, aber irgendwie stehe ich hier komplett auf dem Schlauch, wie meine Eingabe für den CRC Algorithmus aussehen muss. Welche Anpassungen muss ich denn vornehmen? Ich wäre für Hilfe / Tipps sehr dankbar. Gruß Zero |
AW: CRC16 Problem mit Input ASCII/Hex
Wieso liefert deine Funktion immer Result als 0?
> Eine Prozedur oder den CRC als Result. Wieso ist dein Wert 32 Bit (Int32) und keine 16 Bit? Und vor allem: Warum wird Value bzw. crc nirgendwo initialisiert? Zitat:
Ich würde Command[i] vor der inneren Schleife in eine Variable (Byte) kopieren und dann damit arbeiten, anstatt Command zu verändern. Und da es immer nur ASCII EASCII bzw. ANSI ist, würde ich auch einen AnsiString als Parameter verwenden. Zitat:
Manuell (selber Zeichen für zeichen) oder z.B. ![]() Oder noch einen Parameter isHEX in deine Funktion/Prozedur und dann statt ein Zeichen zu nehmen (Ord), jeweils zwei Zeichen nehmen, sie von Hex nach Byte umwandeln und dann damit den CRC berechnen. |
AW: CRC16 Problem mit Input ASCII/Hex
Du mußt die Zeichen als Hex angeben. Und String ist nunmal etwas anderes. In Delphi kannst Du das zB tun, indem Du einfach die Anführungszeichen um den String entfernst und die Zeichen per Raute als Hex identifizierst. Dann noch per Plus-Zeichen konkatenieren. Also zB. so:
Delphi-Quellcode:
Sherlock
command := #02+#0D+#00+#0A+#41+#30+#68+#65+#6C+#6C+#6F;
|
AW: CRC16 Problem mit Input ASCII/Hex
Danke für eure Rückmeldungen.
@Sherlock: Ich hätte erwähnen sollen, dass ich mit Lazarus und FPC programmiere. Deine Variante funktioniert hier an der Stelle so leider nicht. @himitsu: Zitat:
Zitat:
Code:
crc := 0;
Zitat:
Code:
Leider kommt so immer noch etwas falsches heraus ($4D14).
function CalcCRC2(Command: String; var Value: Int32): Integer;
var i,j : Integer; bytecrc : Byte; begin Result := 0; for i:=Start to Length(Command) div 2 do begin bytecrc := HexInByte(MidStr(command, i*2, 2)); for j:=0 to 7 do begin if ((bytecrc and $01) XOR (Value And $0001) <> 0) then Value := (Value shr 1) XOR $A001 else Value := Value shr 1; bytecrc := bytecrc shr 1; end; end; end; |
AW: CRC16 Problem mit Input ASCII/Hex
Zitat:
UND
Delphi-Quellcode:
#$02+#$0D+...
Zitat:
|
AW: CRC16 Problem mit Input ASCII/Hex
Zitat:
In Pascal/Delphi fangen Strings bei 1 an. (außer in den neueren Delphis, wo ARC mit reinpfuscht) |
AW: CRC16 Problem mit Input ASCII/Hex
Zitat:
|
AW: CRC16 Problem mit Input ASCII/Hex
Zunächst, warum nimmst Du nicht das Beispiel aus der Wikipedia?
Zitat:
Gruß K-H Wieso eigentlich ein String als Eingabe? der CRC-Wert wird über eine mehr oder weniger große Anzahl Bytes gebildet. |
AW: CRC16 Problem mit Input ASCII/Hex
Zitat:
Sherlock |
AW: CRC16 Problem mit Input ASCII/Hex
Ich habe mal ein gebastelt, ausgehend von den vorliegenden Beispiel ist dies dabei rausgekommen:
Delphi-Quellcode:
Aber meine Datei-CRC Methode ist glaube ich fehlerhaft an dieser Stelle hier "CRC16 := CalcCRC16(Buff);"
unit uCRC16;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; type TForm1 = class(TForm) LabeledEdit1: TLabeledEdit; LabeledEdit2: TLabeledEdit; Button1: TButton; Button2: TButton; OpenDialog1: TOpenDialog; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} Function CalcCRC16(const Buffer: array of byte) : Word; const Mask: Word = $A001; var CRC: Word; N, I: Integer; B: Byte; begin CRC := $FFFF; for I := Low(Buffer) to High(Buffer) do begin B := Buffer[I]; CRC := CRC xor B; for N := 1 to 8 do if (CRC and 1) > 0 then CRC := (CRC shr 1) xor Mask else CRC := (CRC shr 1); end; Result := CRC; // Result := (IntToHex(CRC, 4)); (* Ausgabe *) end; function FileCRC16(const FileName: string; var CRC16: Word; StartPos: Int64 = 0; Len: Int64 = 0): Boolean; const csBuff_Size = 4096; type TBuff = array[0..csBuff_Size - 1] of Byte; var Handle: THandle; ReadCount: Integer; Size: Int64; Count: Int64; Buff: TBuff; begin Handle := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := Handle <> INVALID_HANDLE_VALUE; if Result then try Int64Rec(Size).Lo := GetFileSize(Handle, @Int64Rec(Size).Hi); if Size < StartPos + Len then begin Result := False; Exit; end; if Len > 0 then Count := Len else Count := Size - StartPos; CRC16 := not CRC16; SetFilePointer(Handle, Int64Rec(StartPos).Lo, @Int64Rec(StartPos).Hi, FILE_BEGIN); while Count > 0 do begin if Count > SizeOf(Buff) then ReadCount := SizeOf(Buff) else ReadCount := Count; ReadFile(Handle, Buff, ReadCount, LongWord(ReadCount), nil); CRC16 := CalcCRC16(Buff); Dec(Count, ReadCount); end; CRC16 := not CRC16; finally CloseHandle(Handle); end; end; // Hier wird CRC16 einer Datei Berechnet procedure TForm1.Button1Click(Sender: TObject); var CRC16: Word; begin CRC16 := 0; if OpenDialog1.Execute then begin if FileCRC16(OpenDialog1.FileName, CRC16) then LabeledEdit2.Text := (IntToHex(CRC16, 4)); end; end; // Hier wird CRC16 eines Strings Berechnet procedure TForm1.Button2Click(Sender: TObject); var s: String; buff: packed array of byte; i: Integer; begin s := LabeledEdit1.Text; SetLength(buff, Length(s)); for i := 0 to (Length(s))-1 do buff[i] := Byte(Ord(s[i+1])); LabeledEdit2.Text := (IntToHex(CalcCRC16(buff), 4)); end; end. Irgendwie hab ich da noch einen Logik-Fehler drinn, komm grad nur nicht drauf wie ich ihn behebe, momentan wird immer eine neue crc16 gegeben ohne die alte zu berücksichtigen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:18 Uhr. |
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 by Thomas Breitkreuz