Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#21

AW: CRC16 Problem mit Input ASCII/Hex

  Alt 10. Apr 2018, 12:51
Hier nochmal eine leicht abgeänderte Variante in der hoffentlich der Datei-Modus korrekt arbeitet aber irgendwie dennoch nicht. Ich komme da nicht weiter. Für die CalcCRC16() wird nun zum Puffer auch noch ein Startwert übergeben. Ob nun $0000 oder $FFFF korrekt ist kann ich noch nicht sagen, so kann jeder bei Laufzeit selbst bestimmen, ich brauch's Hauptsächlich wegen der Datei-Funktion.
Delphi-Quellcode:
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;
    RadioGroup1: TRadioGroup;
    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; inCRC16: Word) : Word;
const
  Mask: Word = $A001;
var
  N, I: Integer;
  B: Byte;
begin
  for I := Low(Buffer) to High(Buffer) do
  begin
    B := Buffer[I];
    inCRC16 := inCRC16 xor B;
    for N := 1 to 8 do
     if (inCRC16 and 1) > 0 then
      inCRC16 := (inCRC16 shr 1) xor Mask
     else
      inCRC16 := (inCRC16 shr 1);
  end;
  Result := inCRC16;
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, CRC16);
      Dec(Count, ReadCount);
    end;
    CRC16 := not CRC16;
  finally
    CloseHandle(Handle);
  end;
end;

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;

procedure TForm1.Button2Click(Sender: TObject);
var
  s: String;
  buff: packed array of byte;
  i: Integer;
begin
  case RadioGroup1.ItemIndex of
   0: 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, Word($0000)), 4));
      end;
   1: begin
       s := LabeledEdit1.Text;
       SetLength(buff, Length(s) div 2);
       for i := 0 to (Length(s) div 2)-1 do
        buff[i] := Byte(StrToInt('$'+s[i*2+1]+s[i*2+2]));
       LabeledEdit2.Text := (IntToHex(CalcCRC16(buff, Word($0000)), 4));
      end;
  end;
end;

end.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat