Comport Verständnisfragen
-
Hi Leute,
ich habe noch ein paar Unklarheiten bezüglich des CompPorts.
Ich habe hier ein Gerät, das dauerhaft einen Statuscode sendet.
- Wieso kann ich per WriteFile() überhaupt "dazwischen" kommen und etwas schicken?
- Wie kann ich sicher sein, dass ich alle Antworten empfange, wenn ich etwas auslesen möchte (jetzt also nicht den Statuscode, sondern eine Antwort nach einer von mir gesendeten Anfrage)? Im Moment lasse ich eine Funktion in einem Thread in einer endlosschleife laufen, die jedes Mal ReadFile() aufruft. Es kann doch sein, dass der ComPort schneller sendet als mein Programm ist und dass ich somit etwas verpasse, oder (ist bestimmt sehr unwahrscheinlich, aber wenn es sich um nen Mikrocontroller handelt erscheint es mir möglich?)?
- Ist der Com Port jetzt bidirektional oder nicht? Auf Grund der Tatsache, dass ich offensichtlich gleichzeitig senden und empfangen kann gehe ich mal davon aus (bin mir aber nicht 100% sicher, ob ich ich wirklich gleichzeitig sende + empfange, denn der Statuscode ist ja immer gleich..)
- Wenn das Gerät z.B. 3 Bytes als Input benötigt, so sehe ich im HTerm, dass das Gerät in der Zeit dann nichts schickt. Ist das wohl auf Seite des Gerätes so implementiert worden, oder ist das irgendwo im Standard vorgesehen?
- Werden die Bits, die an meinem Comport ankommen automatisch irgendwann verworfen? Sprich was passiert, wenn das Gerät eingeschaltet ist, aber kein COM Kabel dran ist?
Ihr seht ich bin echt etwas verwirrt gerade. Eigentlich funktioniert mein Programm soweit. Ich kann Daten senden & in einen Stringbuffer wird dauerhaft gelesen. Aber mich würde dann doch interessieren, in wie weit das Zufall ist.
Wie würde man das eleganter realisieren?
Bedanke mich ganz herzlich fürs Lesen!
-
Wenn man sich alleine den Stecker eines COM-Ports ansieht ist klar das es mit RX und TX jeweils eine eigene Verbindung zum senden und lesen gibt.
Ein "richtiger" Port hat einen FIFO-Puffer der verhindert das wenn der Prozessor gerade mal nichts abholt erstmal auch nichts verloren geht.
Wenn man die Hardware Handshake-Leitungen verwendet wird auch verhindert, das mehr gesendet als empfangen wird. Bei einer oft üblichen 3-Draht-Verbindung muss man ein Software-Handshake implementieren. Man liest also z.B. so lange bis das Zeilenende-Zeichen (oder was anderes) anzeigt, das die Übertragung erstmal komplett ist.
Wie lange man auf weitere Bytes wartet hängt von der eingestellten Baudrate
und dem Timeout ab. Es ist ratsam diese auch zu konfigurieren.Wenn das Gerät sendet, das Kabel aber nicht angeschlossen ist kommt es darauf an ob es eine Antwort erwartet, oder nicht. Wenn niemand zuhört und das Gerät keine Antwort erwartet (Software-Handshake) sind die gesenteten Bytes weg.
Bei Hardware-Handshake wird erst garnicht gesendet.
-
ad 2) Zu Flow-Control hat merano ja schon was geschrieben. Davon abgesehen gibt es Error-Flags mittels derer du z.B. rausbekommen kannst ob der Input-Buffer "übergelaufen" ist. Siehe ClearCommError. Du kannst auch die Grösse des Input Buffers angeben (SetupComm).
ad 3) COM Port ist immer bidirektional und full-duplex. D.h. man kann gleichzeitig Lesen und Schreiben. Im Prinzip sind es zwei vollkommen getrennte Kanäle, einer "raus" und einer "rein".
ad 4) Das ist kein Standard, das macht einfach dein Gerät so.
ad 5) Wenn kein Kabel angehängt ist, dann können auch keine Bits an deinem COM Port ankommen. Was dein Gerät dann macht hängt von deinem Gerät ab.
-
Danke Leute, es wird einiges klarer.
Sehe ich also richtig, dass der durch CreateFile erzeugt Handle einen internen Puffer besitzt und besser auch abfragen sollte, ob dieser übergelaufen ist und somit ggf. die Übertragung neu starten muss?
Wie ist es denn gängig eine Funktion zu implementieren, die dauerhaft vom Com Port liest und in einen großen Puffer schreibt?
Da gibt es doch bestimmt elegantere Lösungen, als ReadFile(..) dauerhaft in einer Endlosschleife laufen zu lassen?Wartet denn ReadFile(..) auf den Empfang, oder hat die Funktion einen integrierten Timeout, wird das über CreateFile bereits eingebaut (denn ich übergebe ja den Com-Port, die Baudrate und so)?
Sollte ich also beim Aufruf von ReadFile() auch noch einen Timeout einbauen, oder gar die Baudrate noch beachten?Danke euch!
Schöne Grüße,
jakap
-
Um das ganze etwas abzukürzen hier ein Gerüst als kleine Aufbauhilfe.
Die Systemaufrufe kann man ja mal in der MSDN-Hilfe nachlesen ...HANDLE hcom; char strPort[8]; ... hcom = CreateFileA( strPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); DCB dcb; GetCommState( hcom, &dcb ) ) dcb.BaudRate = CBR_115200; ... SetCommState( hcom, &dcb ); SetupComm(hcom, 1024, 1024); COMMTIMEOUTS commtimeouts; GetCommTimeouts( hcom, &commtimeouts ); commtimeouts.ReadIntervalTimeout = 0; ... SetCommTimeouts( hcom, &commtimeouts );Die jeweiligen Werte hängen natürlich von den Gegebenheiten ab

-
-
Serielle Kommunikation ist nicht einfach. Ich empfehle auch auf jeden Fall das Projekt von Codeproject
-
Ich gucke mir die Klassen an.
Die sind in Ordnung und so wird das gemacht?
-
jakap schrieb:
Die sind in Ordnung und so wird das gemacht?

Ja. Alternative gibts bei Boost.Asio auch eine Implementation für serielle Kommunikation.
-
Okay.
Mir gehts halt auch darum, einigermaßen zu verstehen, wie das Ganze funktioniert und nicht "nur" die lib zu benutzen. Die boost Lib hat mich regelrecht erschlagen, denke da ist die "kleinere" Lösung für den Anfang besser, oder?