Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Binär Datei über RS232 versenden Delphi (https://www.delphipraxis.net/134345-binaer-datei-ueber-rs232-versenden-delphi.html)

itblumi 20. Mai 2009 10:33


Binär Datei über RS232 versenden Delphi
 
Ich versuch seit einiger Zeit eine Binär Datei über eine RS232 Schnittstelle zu versenden, aber aus irgendeinem Grund bricht er nach dem ersten Byte ab.
Mein Code Bis jetzt:

Delphi-Quellcode:
       
   AFileStream := TFileStream.Create(DatName, fmOpenRead);
        try
          DataSize := AFileStream.Size;
          AFileStream.Position := 0;
          CanSend := 1;
          GetMem(DataPtr, CanSend);
          while DataSize > 0 do begin
            AFileStream.Read(DataPtr, CanSend);
            Move(DataPtr, SendByte, CanSend);
            ComSerial.SendByte(SendByte);
            DataSize := DataSize - CanSend;
            SendDataSize := SendDataSize + CanSend;
          end;
          FreeMem(DataPtr);
        finally
          AFileStream.Free;
        end;

Hat irgendjemand eine Idee?

Satty67 20. Mai 2009 10:40

Re: Binär Datei über RS232 versenden Delphi
 
Soll CanSend später größer werden? Ansonsten könntest Du ja auf den DataPtr verzichten und die StreamDaten gleich in SendByte einlesen.

Ich glaube das müsste so aussehen:
Delphi-Quellcode:
Move(DataPtr^, SendByte, CanSend);
was aber erst mal nur für falsche Daten gesorgt hätte.

itblumi 20. Mai 2009 12:04

Re: Binär Datei über RS232 versenden Delphi
 
Ich habe auch so das selbe Problem und zwar das er mit dem ersten gesendeten Byte aus dem Redboot rausspringt und den Versuch abbricht. Das bringt mich in der Hinsicht trotzdem nicht weiter. Eine weiter Möglichkeit für mich wäre. Das ich die Daten direkt mit SendData(Pointer, DataSize) an den ComPort schicke das funktioniert aber auch nicht so wie es sein soll.

Diese Routine sieht dann so aus:

Delphi-Quellcode:
          AFileStream := TFileStream.Create(DatName, fmOpenRead);
        try
          DataSize := AFileStream.Size;
          AFileStream.Position := 0;
          CanSend := 1;
          GetMem(DataPtr, CanSend);
          while DataSize > 0 do begin
            AFileStream.Read(DataPtr, CanSend);
            ComSerial.SendData(DataPtr, CanSend);
            DataSize := DataSize - CanSend;
            SendDataSize := SendDataSize + CanSend;
          end;

        finally
          AFileStream.Free;
          FreeMem(DataPtr);
        end;
Doch bei diesem Versuch empfange ich überhaupt keine Daten an meiner Gegenstelle.

Das CanSend ist blos noch dabei weil ich vorher Daten mit einer Größe von 2048 verschickt habe und
sich die SendeGröße beim letzten Sendevorgang geändert hat.

nicodex 20. Mai 2009 12:12

Re: Binär Datei über RS232 versenden Delphi
 
TStream.Read() erwartet einen untypisierten Parameter (Inhalt beliebigen Typs). Wenn du einen Zeiger hast, dann musst du ihn dereferenzieren, um auf den Inhalt zu zeigen (DataPtr^, ...).
Dein jetziger Code überschreibt den Zeiger (und die im Speicher nachfolgenden Daten), was sicher nicht beabsichtigt ist.

itblumi 20. Mai 2009 12:26

Re: Binär Datei über RS232 versenden Delphi
 
Jetzt habe ich wieder das selbe Problem das er sofort nach dem ersten senden den Vorgang abbricht.


RedBoot> ^C
RedBoot> fload
CCCan't load '<null>': Cancelled

itblumi 20. Mai 2009 12:55

Re: Binär Datei über RS232 versenden Delphi
 
Im PComm Terminal machen sie das selbe, aber die Daten die geschickt werden sehen anders aus wie meine, obwohl es die selbe Datei ist.
Sie benutzen da auch das Protokoll X-Modem crc um Binäre Daten zu verschicken.

Kann es vllt an der Art wie ich die Daten aus der Datei lese liegen?

Klaus01 20. Mai 2009 13:05

Re: Binär Datei über RS232 versenden Delphi
 
Spricht Deine Gegenstelle denn das Protokoll XModem?
Wenn ja, dann solltest Du bzw. Dein Programm es auch sprechen.
XModem

Grüße
Klaus

itblumi 11. Jul 2009 17:09

Re: Binär Datei über RS232 versenden Delphi
 
Hab jetzt endlich wieder Zeit zum Delphi programmieren und hänge bei der CRC Berechnung.

Danke übrigens für den Tip Klaus CRC XModem ist die Lösung oder sollte sie sein.

Ich komme einfach nicht auf die Checksum die vom PComm Terminal errechnet wird.
Hier ein Auszug aus einem gesendeten Block:

01 01 FE 18 F0 9F E5 18 F0 9F E5 18 F0 9F E5 18 F0 9F E5 18 F0 9F E5 00 00 00 00 18 F0 9F E5 18 F0 9F E5 40 00 00 60 20 02 00 60 44 02 00 60 70 02 00 60 8C 02 00 60 00 00 00 00 8C 03 00 60 54 03 00 60 40 15 9F E5 B0 00 D1 E1 FF 00 80 E3 B0 00 C1 E1 B4 00 D1 E1 FF 00 80 E3 B4 00 C1 E1 B8 00 D1 E1 FF 00 80 E3 B8 00 C1 E1 1B 13 A0 E3 18 05 9F E5 B0 00 C1 E1 B4 00 C1 E1 10 05 9F E5 B8 00 C1 E1 F0 FC

01 01 FE = Ist die Initialisierung mit Begin eines Blockes(01), Block Nummer(01), Komplement der Block Nummer (FE)
F0 FC = Checksum CRC XModem

Bei mir kommt als Checksum immer nur 70D8 raus, was mach ich blos falsch?

Hier ein Auszug aus dem Code mit dem ich die Checksum berechne

Delphi-Quellcode:
function CalculateXYZModemCRC16(const Data; Length: LongWord): Word;
type
  TCRC16Table = array[0..255] of Word;
  TBytes = array[0..MaxInt - 1] of Byte;

    const Crc16Tab: Array[0..$FF] of Word =
    ($00000, $01021, $02042, $03063, $04084, $050a5, $060c6, $070e7,
     $08108, $09129, $0a14a, $0b16b, $0c18c, $0d1ad, $0e1ce, $0f1ef,
     $01231, $00210, $03273, $02252, $052b5, $04294, $072f7, $062d6,
     $09339, $08318, $0b37b, $0a35a, $0d3bd, $0c39c, $0f3ff, $0e3de,
     $02462, $03443, $00420, $01401, $064e6, $074c7, $044a4, $05485,
     $0a56a, $0b54b, $08528, $09509, $0e5ee, $0f5cf, $0c5ac, $0d58d,
     $03653, $02672, $01611, $00630, $076d7, $066f6, $05695, $046b4,
     $0b75b, $0a77a, $09719, $08738, $0f7df, $0e7fe, $0d79d, $0c7bc,
     $048c4, $058e5, $06886, $078a7, $00840, $01861, $02802, $03823,
     $0c9cc, $0d9ed, $0e98e, $0f9af, $08948, $09969, $0a90a, $0b92b,
     $05af5, $04ad4, $07ab7, $06a96, $01a71, $00a50, $03a33, $02a12,
     $0dbfd, $0cbdc, $0fbbf, $0eb9e, $09b79, $08b58, $0bb3b, $0ab1a,
     $06ca6, $07c87, $04ce4, $05cc5, $02c22, $03c03, $00c60, $01c41,
     $0edae, $0fd8f, $0cdec, $0ddcd, $0ad2a, $0bd0b, $08d68, $09d49,
     $07e97, $06eb6, $05ed5, $04ef4, $03e13, $02e32, $01e51, $00e70,
     $0ff9f, $0efbe, $0dfdd, $0cffc, $0bf1b, $0af3a, $09f59, $08f78,
     $09188, $081a9, $0b1ca, $0a1eb, $0d10c, $0c12d, $0f14e, $0e16f,
     $01080, $000a1, $030c2, $020e3, $05004, $04025, $07046, $06067,
     $083b9, $09398, $0a3fb, $0b3da, $0c33d, $0d31c, $0e37f, $0f35e,
     $002b1, $01290, $022f3, $032d2, $04235, $05214, $06277, $07256,
     $0b5ea, $0a5cb, $095a8, $08589, $0f56e, $0e54f, $0d52c, $0c50d,
     $034e2, $024c3, $014a0, $00481, $07466, $06447, $05424, $04405,
     $0a7db, $0b7fa, $08799, $097b8, $0e75f, $0f77e, $0c71d, $0d73c,
     $026d3, $036f2, $00691, $016b0, $06657, $07676, $04615, $05634,
     $0d94c, $0c96d, $0f90e, $0e92f, $099c8, $089e9, $0b98a, $0a9ab,
     $05844, $04865, $07806, $06827, $018c0, $008e1, $03882, $028a3,
     $0cb7d, $0db5c, $0eb3f, $0fb1e, $08bf9, $09bd8, $0abbb, $0bb9a,
     $04a75, $05a54, $06a37, $07a16, $00af1, $01ad0, $02ab3, $03a92,
     $0fd2e, $0ed0f, $0dd6c, $0cd4d, $0bdaa, $0ad8b, $09de8, $08dc9,
     $07c26, $06c07, $05c64, $04c45, $03ca2, $02c83, $01ce0, $00cc1,
     $0ef1f, $0ff3e, $0cf5d, $0df7c, $0af9b, $0bfba, $08fd9, $09ff8,
     $06e17, $07e36, $04e55, $05e74, $02e93, $03eb2, $00ed1, $01ef0);
var
  CRC16: word;
  index: byte;
  i:LongWord;
begin
  CRC16 := 0; // $FFFF
  for i:=0 to Length-1 do
  begin
    index := ((CRC16 shr 8) xor TBytes(Data)[i]) and $FF;
    CRC16 := CRC16Tab[Index] xor (CRC16 shl 8);
  end;
  Result := CRC16;
end;

gammatester 11. Jul 2009 22:47

Re: Binär Datei über RS232 versenden Delphi
 
Wenn Du die ersten drei Bytes (01 01 FE) wegläßt, erhältst Du den gewünschten CRC-Wert $F0DC.

Gruß Gammatester

itblumi 11. Jul 2009 23:39

Re: Binär Datei über RS232 versenden Delphi
 
Ich lasse sie ja weg und komme irgendwie trotzdem nicht auf den Wert.

Hier mal noch mein Funktionsaufruf mit dem ich teste.

Delphi-Quellcode:

procedure TFWork.TestCRCClick(Sender: TObject);
var
   AFile, AStr: String;
  SendByte: Byte;
  Data: Array [1..128] of Byte;
   AFileStr: TFileStream;
  i, crc: Integer;
  Erg: Word;
begin
  AFile := Fu.GetExeDir + 'test.bin';
   if FileExists(AFile) then begin
     AFileStr := TFileStream.Create(AFile, fmOpenRead);
    try
      AFileStr.Position := 0;
      for i:=1 to 128 do begin
        AFileStr.Read(SendByte,1);
        Data[i] := SendByte;
      end;
      crc := Fu.CalculateXYZModemCRC16(Data, High(Data));
      EdBefSer.Text := IntToHex(crc, 4);
    finally
      AFileStr.Free;
    end;
  end;
end;


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

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