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


von Robert Weise (Gast)


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)


Lesenswert?


von Robert Weise (Gast)


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)


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)


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)


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:
1
function TBPMConnectionV24.OpenConn : boolean;
2
3
var CPDCB : TDCB;
4
    pFN : PChar;
5
    Timeouts : CommTimeouts;
6
7
  procedure set_dcbflag (v : word);
8
  begin
9
  CPDCB.Flags := CPDCB.Flags or v;
10
  end;
11
12
  procedure res_dcbflag (v : word);
13
  begin
14
  CPDCB.Flags := CPDCB.Flags and not v;
15
  end;
16
17
begin
18
Result := true;
19
if CHandle > 0 then exit;
20
Result := false;
21
pFN := @Name[1];
22
CHandle := CreateFile (pFN,GENERIC_READ + GENERIC_WRITE,0,nil,OPEN_EXISTING,
23
                          File_Flag_Write_Through or File_Flag_No_Buffering,0);
24
if CHandle = INVALID_HANDLE_VALUE then CHandle := 0 else
25
  begin
26
  fillchar (CPDCB,SizeOf (TDCB),0);
27
  with CPDCB do
28
    begin
29
    DCBlength := SizeOf (TDCB);
30
    BaudRate := CBR_9600;
31
    Flags := fParity or fOutxCtsFlow or fDtrControlEnable
32
             or fErrorChar or fRtsControlEnable;
33
    ByteSize := 8;
34
    Parity := EVENPARITY;
35
    StopBits := ONESTOPBIT;
36
    ErrorChar := '?';
37
    EofChar := chr (13);
38
    end;
39
  if SetCommState (CHandle,CPDCB) then
40
    begin
41
    Timeouts.ReadIntervalTimeout := 100;
42
    Timeouts.ReadTotalTimeoutMultiplier := 2;
43
    Timeouts.ReadTotalTimeoutConstant := 1000;
44
    Timeouts.WriteTotalTimeoutMultiplier := 2;
45
    Timeouts.WriteTotalTimeoutConstant := 1000;
46
    if SetCommTimeouts (CHandle, Timeouts) then Result := true;
47
    end;
48
  if Result then
49
    begin
50
    if not SetCommMask (CHandle,EV_BREAK  or EV_ERR  or EV_RXFLAG
51
       or EV_TXEMPTY) then Result := false;
52
    end;
53
  if not Result then
54
    begin
55
    CloseHandle (CHandle);
56
    CHandle := 0;
57
    end;
58
  end;
59
UnUsed := 0;
60
end;
61
62
function  TBPMConnectionV24.DoReceiveString : boolean;
63
var rdok : boolean;
64
begin
65
rdok := false;
66
if CHandle > 0 then
67
  begin
68
  rdok := ReadFile (CHandle,RxMessage,255,BytesRead,nil);
69
  if BytesRead = 0 then
70
    begin
71
    rdok := false;
72
    end;
73
  end;
74
Result := rdok;
75
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 Pandur S. (jetztnicht)


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


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)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.