Seite 1 von 1
QextSerialPort::readLine() Problem
Verfasst: 20. April 2011 14:10
von Muckl
Hallo,
Ich beginne mal ein neues Thema, da mein altes "QSerialDevice Problem" nicht mehr ganz aktuell ist.
Ich lesen mit QExtserialPort Daten von einer Seriellen Schnittstelle. Ich habe ein Timer der alle 100ms die readLine() Funktion ausführt. Danach parse ich die Daten. Mein Problem ist, dass readLine() entweder eine ganze Zeile einliest, oder so viel bis die maximale Schriftzeichenanzahl erreicht ist oder bis keine Daten mehr vorhanden sind. Das letzte ist genau mein Problem, gelegtenlich wird nicht die ganze Zeile eingelesen, sodern der Rest der Zeile erst im nächsten Zeitschritt. Dies führt dazu, dass mein Parser auf einen Index (QStringList[Index]) zugreifen will, der nicht vorhanden ist, da die Zeile ja abgeschnitten wurde. Ist es möglich, dass readLine so lange einliest, bis die Zeile wirklich voll ist und nicht vorher aufhört, da keine Daten mehr vorhanden sind? Oder hat jemand eine andere Idee?
Gruß,
Muckl
Verfasst: 20. April 2011 18:36
von Christian81
Daten zwischenspeichern und das nächste Mal parsen.
Verfasst: 21. April 2011 08:49
von Muckl
moin,
ja, das problem ist, dass die Zeilen nciht alle gleich lang sind. Dann müsste ich ja vorher prüfen, um welche Zeile es sich handelt, dann ob die komplette länge eingelesen wurde und dann einen parser für das parsen der ganzen Zeile und einen variablen parser zum parsen von Bruchstücken erstellen.
Habe das jetzt so gemacht, dass er jeden Charakter einzeln einliest und so lange an einen QString ranhängt, bis "\n" kommt. Die Zeilen werden nun komplett eingelesen, jedoch muss ich ja vorher abfragen, ob überhaupt daten vorhanden sind und so lange keine vorhanden sind, sitzt er für die zeit in einer Dauerschleife. Was dann für ein paar ms das Einfrieren der GUI zur folge hat. (merkt man nur beim verschieben der GUI). Aber vielleicht kann man das mit einem kurzen Timeout für z.B. 50ms beheben.
Ein anderes Problem ist noch, dass die Schnittstelle, ( wenn man mal keine Daten ausliest), bis zu 4096 Zeichen abspeichert. Starte ich dann das auslesen wieder, muss er erstmal diese daten auslesen, bis er an die aktuellen Daten kommt. Kann man diesen Puffer deaktivieren. Ich habe schon viel Gegoogle, jedoch keine wirklich gute Dokumentation von QEXTSerialPort gefunden.
http://qextserialport.sourceforge.net/ hier sind zwar alle Klassen und Methoden angegeben, jedoch wird nciht gesagt, was sie bewirken.
gruß,
Muckl
Verfasst: 21. April 2011 09:00
von Christian81
Ein Stream ist nunmal ein Stream der kein Anfang und Ende hat. Diesen muss man sich über geeignete Start/Endemarkierungen selbst holen. Ist aber kein serial-spezifisches Problem sondern ein allgemeines.
Verfasst: 21. April 2011 12:31
von bronko
evtl. hilft dir das SLIP Protokoll oder etwas änliches
Verfasst: 23. April 2011 18:35
von Ritchie
Hallo Muckl,
warum liest Du die Daten von der seriellen Schnittstelle nicht in einem
parallelen Thread ein und übergibst Deinem Hauptprogramm ein Flag,
welches kennzeichnet, das ein Datenpaket korrekt eingelesen wurde ?
Gruss R.
Verfasst: 26. April 2011 13:08
von Muckl
Hallo bronko und Ritchie,
vielen Dank für die Antwort.
So wie du vorgeschlagen hast, mach ich das jetzt Multithreaded. Dies ist mal wieder Neuland für mich, aber mit QT scheint das nciht sonderlich schwer zu sein.
Gruß,
Muckl
Verfasst: 29. April 2011 14:50
von Muckl
Hallo,
es läuft nun mit zwei Threads. Das Hauptfenster ist der MainThread und dieser erstellt dann den zweiten Thread, der den Port öffnet und die Daten list. Nun muss man ja, um den Port zu öffnen, bzw. die Daten zu lesen, Portsettings eingeben. Diese möchte ich über ein zweitest QWidget eingeben. Um kurz meine Klassen und DateiStruktur zu erklären: Ich habe eine "Main", eine MainWindow.cpp sowie MainWindow.h die zur Erzeugung des Hauptfensters benötigt werden und eine SerialPort.cpp und SerialPort.h die als zweiter Thread zum lesen der Daten da sind. Ich habe mir nun mit dem Designer ein Widget erstellt und in der SerialPort.h eine Instanz dieses Widget erstellt. Nun müsste ich doch mit der show() Methode innerhalb von Mainwindow.cpp dieses Widget öffnen können.
Meine Frage ist nun, ob dies überhaupt der richtige Weg ist, um ein zusätzliches Fenster zu öffnen ? Ich Poste mal etwas Quellcode, wie ich mir das vorstelle. Hier ist alles für den Thread und das Hauptfenster weggelassen. Diese Sachen laufen ja.
SerialPort.h
Code: Alles auswählen
#include "ui_SerialPort.h"
class SerialPort : public QThread, public QWidget
{
Q_OBJECT
public:
SerialPort();
private:
Ui::SerialPort settings;
};
SerialPort.cpp
Mainwindow.cpp
Code: Alles auswählen
MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
MyPort.show();
}
MainWindow.h
Code: Alles auswählen
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
~MainWindow();
private:
SerialPort MyPort;
};
Zusätzliche Frage ist: Warum kann ich mit MyPort.show() das Fenster öffnen? Eigentlich müsste es doch MyPort.Settings.show() sein. Jedoch wird es beim öffnen des Hauptfensters auch so gemacht, ohne die Instanz mit anzugeben. Also, wenn ich das so laufen lasse, offnet er nicht das von mir erstellte Widget, sondern einfach ein leeres!?!?!
Besten Dank,
gruß,
Muckl
Verfasst: 29. April 2011 16:50
von Christian81
Vergiss die Threads. Das ganze geht auch ohne. Und wenn Du wirklich Threads verwenden willst dann
LIES DIE DOKU zu QThread und schmeiss nicht einfach alles zusammen was Du gerade so findest. Nur weil man von QThread ableitet läuft es nicht automatisch in einem anderen Thread. Ganz zu schweigen dass GUI-Objekte und Operationen nur im Hauptthread ausgeführt werden dürfen. Das ganze funktioniert prima ohne Threads...

Verfasst: 29. April 2011 17:36
von Muckl
Moin,
also, dass mti den Threads fuktioniert eigentlich super. Ich glaube, ich werde auch nicht drum herum kommen, da später evtl auch noch daten von anderen Schnittstellen zeitgleich eingelesen werden sollen. Und sämtliche daten auch noch verarbeitet werden müssen. Das mit den Threads habe ich mir auch schon angeguckt. Ich habe jetzt nur den ganzen Threadkram nciht mit in den obigen Code reingetan, da es mir darum garnciht mehr geht. Was du sagtest, von wegen, GUI darf nur im Hauptthread. wenn das so ist, dann funktioniert dass wohl so wie ich das dachte nicht. Dann muss ich mir wohl was anderes überlegen, die Schnittstelle modularisiert hin zu bekommen. Wie ist denn das, kann man zwei gleichwertige Threads erzeugen, die dann beide GUI Objekte beinhalten dürfen?
Gruß,
Muckl
Verfasst: 29. April 2011 18:05
von Willi2793
Nähern wir uns der Frage dochmal mit einer Gegenfrage an: Wenn Du 2 gleichwertige Threads hättest, welcher davon wäre denn der erwähnte Hauptthread?
Verfasst: 29. April 2011 18:11
von Muckl
jo, stimmt schon. Bei mir habe ich bis jetzt einen Hauptthread. Jedoch habe ich weiter oben den Tipp bekommen zwei parallele Threads zu nehmen. Dadrunter würde ich verstehen, dass es zwei gleichwertige sind. Aber deiner Frage entnehme ich, dass es wohl nciht geht.
Verfasst: 29. April 2011 19:17
von Willi2793
Parallel laufend heißt nicht gleichberechtigt