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

Gast #4855377
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
Gast #4856273
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.
Gast #4856578
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
#4856660
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.
Persönliche Seite #4945385
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.
Gast #4951585
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren