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
..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...
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.
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
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
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.