Forum: PC-Programmierung Delphi 7: Comport auslesen, Byte-Weise oder per Stop-Zeichen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Robert Weise (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich versuche schon eine Weile mit Delphi unter XP eine gesendete 
Zeichenkette vom virtuellen Comport auszulesen. Aber es klappt irgendwie 
nicht. Habe mir die Komponente Cport runtergeladen und eingebunden.

"ComPort.ReadStr(String, Count);"

damit bekomme ich Strings vom Com-Port ausgelesen, welche wohl als 
Endtermination NULL haben, also 0-Byte. Ist nur etwas ungünstig, wenn 
man 0-Byte in der Übertragung hat. Daher wollte ich den Comport 
Byte-Weise auslesen oder halt bis zu einem definierten End-Zeichen.
Bei der Komponente cport gibt es ja einige Möglichkeiten, nur irgendwie 
sehe ich wohl den Wald vor lauter Bäumen nicht bzw die Möglichkeit

"ComDataPacket1.StopString := #3;"
aber das bekomme ich nicht eingebunden, es kommen immer 
Fehlermeldungen...

Wer hat da eine Idee? Vielen Dank

von andreasgf (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von Robert Weise (Gast)


Bewertung
0 lesenswert
nicht lesenswert
..ja, da wird die übliche Vorgehensweise mit String-Auslesen 
(Readstr)gezeigt, welche bei mir ja nicht funktioniert bzw. anwendbar 
ist, daher habe ich diesen Beitrag eröffnet...

von торфкопф (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vielleicht nicht mit strings arbeiten, sondern mit bytes ?
Mit nullterminierten Strings ueber das Comport zu arbeiten erscheint mir 
eh etwas seltsam.

Ich empfehle nun mal Asynch Pro - turbo Asynch plus. Mittlerweile gratis 
bei Sourceforge.

von Heiko G. (heikog)


Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Dann sollte man stattdessen Comport1.Read(Buffer,Count) verwenden 
können, notfalls mit count=1 wenn man nicht weiss wie viele Zeichen 
empfangen wurden.

(Ich hab mir nur den ComPort Library Quellcode angesehen, ich verwende 
diese Komponente nicht selbst)

Heiko

von Georg (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Robert Weise schrieb:
> Habe mir die Komponente Cport runtergeladen und eingebunden

Dabei kann ich dir nicht helfen, ich verwende dafür keine zusätzlichen 
Libraries, sondern ganz schlicht und einfach die Windows-Funktionen:
function TBPMConnectionV24.OpenConn : boolean;

var CPDCB : TDCB;
    pFN : PChar;
    Timeouts : CommTimeouts;

  procedure set_dcbflag (v : word);
  begin
  CPDCB.Flags := CPDCB.Flags or v;
  end;

  procedure res_dcbflag (v : word);
  begin
  CPDCB.Flags := CPDCB.Flags and not v;
  end;

begin
Result := true;
if CHandle > 0 then exit;
Result := false;
pFN := @Name[1];
CHandle := CreateFile (pFN,GENERIC_READ + GENERIC_WRITE,0,nil,OPEN_EXISTING,
                          File_Flag_Write_Through or File_Flag_No_Buffering,0);
if CHandle = INVALID_HANDLE_VALUE then CHandle := 0 else
  begin
  fillchar (CPDCB,SizeOf (TDCB),0);
  with CPDCB do
    begin
    DCBlength := SizeOf (TDCB);
    BaudRate := CBR_9600;
    Flags := fParity or fOutxCtsFlow or fDtrControlEnable
             or fErrorChar or fRtsControlEnable;
    ByteSize := 8;
    Parity := EVENPARITY;
    StopBits := ONESTOPBIT;
    ErrorChar := '?';
    EofChar := chr (13);
    end;
  if SetCommState (CHandle,CPDCB) then
    begin
    Timeouts.ReadIntervalTimeout := 100;
    Timeouts.ReadTotalTimeoutMultiplier := 2;
    Timeouts.ReadTotalTimeoutConstant := 1000;
    Timeouts.WriteTotalTimeoutMultiplier := 2;
    Timeouts.WriteTotalTimeoutConstant := 1000;
    if SetCommTimeouts (CHandle, Timeouts) then Result := true;
    end;
  if Result then
    begin
    if not SetCommMask (CHandle,EV_BREAK  or EV_ERR  or EV_RXFLAG
       or EV_TXEMPTY) then Result := false;
    end;
  if not Result then
    begin
    CloseHandle (CHandle);
    CHandle := 0;
    end;
  end;
UnUsed := 0;
end;

function  TBPMConnectionV24.DoReceiveString : boolean;
var rdok : boolean;
begin
rdok := false;
if CHandle > 0 then
  begin
  rdok := ReadFile (CHandle,RxMessage,255,BytesRead,nil);
  if BytesRead = 0 then
    begin
    rdok := false;
    end;
  end;
Result := rdok;
end;

Der wensetliche "Trick" ist, ein Zeichen für das Ende der Message zu 
definieren (eofchar, hier CR). Das ist keine Delphi-Frage, auch keine 
Windows-Frage, sondern eine Frage schlichter Logik: woher soll das 
Programm sonst wissen, wann eine Message vollständig gesendet ist? Das 
geht nur so oder per Timeout.

Georg

von Joggel E. (jetztnicht)


Bewertung
0 lesenswert
nicht lesenswert
Sinnvollerweise verwendet man ein Protokoll, das die Laenge gleich zu 
Beginn der Meldung enthaelt.
Oder wahlweise indem man Strings als Delphi Strings uebertraegt, dh das 
Byte vor dem String ist die nachfolgende Laenge.

Man sollte immer etwas zum Zaehlen haben, das vereinfacht die 
Zustandsmaschine beim Empfang.

: Bearbeitet durch User
von Joe G. (feinmechaniker) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Robert Weise schrieb:
> "ComPort.ReadStr(String, Count);"
>
> damit bekomme ich Strings vom Com-Port ausgelesen, welche wohl als
> Endtermination NULL haben, also 0-Byte. Ist nur etwas ungünstig, wenn
> man 0-Byte in der Übertragung hat.

Vielleicht ist ja eine Lösung noch interessant für dich.
Das Stringende NULL kannst du mit ComPort.DiscardNull := false; 
abschalten.

von W.S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Robert Weise schrieb:
> damit bekomme ich Strings vom Com-Port ausgelesen, welche wohl als
> Endtermination NULL haben, also 0-Byte.

Ja zum Kuckuck, dann schau doch mal in den Quellcode deiner 
ComPort-Komponente. Vom Betriebssystem aus sieht das ganz anders aus: Da 
kann man die Anzahl der Zeichen ermitteln, die das OS 
zwischengespeichert hat und entweder alle oder einen Teil davon in einen 
eigenen Puffer transferieren lassen. Strings gibt es da nicht, sondern 
nur bestimmte Anzahl von Zeichen die man haben will.

Wenn deine Komponente das verhunzt, dann ist sie eben schlecht 
geschrieben.
Bei neueren Delphi's gibt es noch eine Änderung: den Übergang bei String 
von 8 auf 16 Bit. Da muß man dann dediziert mit AnsiString arbeiten. 
Sollte aber m.E. bei D7 noch nicht relevant sein.

W.S.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.