Kurze, schmerzlose Frage: Unter C würde man auf Linux die serielle Schnittstelle wohl über termios.h ansprechen. Gibts da in C++ (ohne Frameworks wie Qt oder Boost) was "moderneres"? Grüße, Karl
Um es kurz zu machen, nein. Die Ansteuerung von seriellen oder anderen Schnittstellen ist betriebssystem- und hardwarespezifisch und nicht Bestandteil der C++-Standardbibliotheken.
Matthias H. schrieb: > Um es kurz zu machen, nein. Die Ansteuerung von seriellen oder > anderen > Schnittstellen ist betriebssystem- und hardwarespezifisch und nicht > Bestandteil der C++-Standardbibliotheken. wxwidgets mit der CTB von Joachim Bürmann konnte das ganz gut, ging unter Windows, Linux und MAC OS. https://iftools.com/opensource/ctb.de.php
Noch ein kleiner Nachtrag: termios.h usw. ist nur notwendig, wenn tatsächlich ein Terminal über irgendwelche Steuerzeichen angesprochen werden soll. Für "normale" Anwendungen, wo man nur irgendwelche Daten lesen oder schreiben möchte, wäre das klassische Vorgehen unter UNIX, daß man über open() das entsprechende Device aufmacht, über ioctl() Baudrate, Handshake-Leitungen u. ä. setzt und über read() und write() Daten liest oder schreibt (wahlweise mit asynchronem I/O). Ich würde empfehlen, sich eine passende Klassenbibliothek zu suchen oder zumindest eine Wrapperklasse zu schreiben, denn mit den nackten Betriebssystemaufrufen macht es einfach keinen Spaß, gerade die Fehlerbehandlung.
Ja, das hab ich mir fast gedacht. Ich werde mir dann eben eine Wrapperklasse mit "Komfort"routinen schreiben. Spricht eigentlich irgendwas dagegen, im Konstruktor dieser klasse einen neuen (p)thread zu erstellen? Dieser könnte dann Daten nmit select() einlesen und einen Puffer befüllen, während das eigentliche Programm weiterläuft. Soviele serielle Verbindungen hat man ja normal nicht offen, sodass plötzlich Unmengen an Threads laufen...
Hallo Karl, > Spricht eigentlich irgendwas dagegen, im Konstruktor dieser klasse einen neuen > (p)thread zu erstellen? Dieser könnte dann Daten nmit select() einlesen und > einen Puffer befüllen, während das eigentliche Programm weiterläuft. Da spricht nichts dagegen, ich habe das schon öfters so gemacht. Meistens mache ich es so, daß die "Arbeitsfunktion" des Threads einen Zeiger auf die Objektinstanz der Schnittstellen-Wrapperklasse übergeben bekommt und nach den entsprechenden Type Casts eine Worker-Methode in der "Schnittstellenklasse" aufruft. Der Zugriff auf den verwendeten Puffer muß synchronisiert werden, z. B. über eine Mutex-Semaphore. Eine einfache, wenn auch nicht sehr effiziente Möglichkeit für solch einen Puffer wäre ein STL-String. Allerdings mußt Du bei Threads, Semaphoren usw. wiederum eine ganze Menge Fehlerbehandlung usw. machen, daher würde ich wirklich empfehlen, daß Du eine Klassenbibliothek nimmst und es nicht alles selbst machst, es sei denn, um zu lernen, wie es geht. Tschüß, Matthias
So, war leider die letzten Tage unterwegs und konnte nicht mehr reinschaun. Danke dir Matthias! Ich bin in C++ nicht so bewandert (deswegen eben diese Fingerübung), aber ist ein std::vector<char> nicht besser geeignet als ein std::string? Ich meine, über die Serielle werden ja auch Binärdaten übertragen. Ansonsten: Ich habe vor längerer Zeit einen Bootloader (PC-Seite) für meine AVR-Projekte geschrieben, in reinem C. Als Übung wollte ich diesen nun auf C++ umschreiben. Leider fallen mir hier einige Sachen auf die mich stören. Allen vorran die Tatsache, dass ich in meinem Klassenheader Informationen über die interne Umsetzung preisgeben muss (Stichwort: private Attribute). Und spätestens wenn ich mehrere Klassen habe die andere Klassen als Attribut verwenden habe ich dermaßen viele Folge-Includes, dass die "oberste" Kompiliereinheit über das halbe Projekt "Bescheid weis". Das stößt mir bisl sauer auf, weil ich in C sehr darauf geachtet habe, Interface (Header) und Implementierung (C-File) zu trennen... Ich werde das Projekt mal noch abschließen und danach neu beurteilen, ob C++ das richtige für mich ist :-) Grüße, Karl
> Und spätestens wenn ich mehrere Klassen habe die andere Klassen als > Attribut verwenden habe ich dermaßen viele Folge-Includes, dass die > "oberste" Kompiliereinheit über das halbe Projekt "Bescheid weis". > Das stößt mir bisl sauer auf, weil ich in C sehr darauf geachtet habe, > Interface (Header) und Implementierung (C-File) zu trennen... Diese Klassen wirst Du als Zeiger oder Objektreferenz übergeben und dafür reicht eine "Forward Deklaration". Einen Header musst du dann nicht einbinden. Nur für Datentypen, die kein Zeiger oder eine Referenz sind, musst Du Header einbinden. Du musst dich mit C++ mehr beschäftigen. Möchtest Du das nicht, dann ist C++ nicht das richtige für dich! Gute Buch ist "Der C++ Programmierer" von Ulrich Beymann.
Hallo Karl, Karl schrieb: > So, war leider die letzten Tage unterwegs und konnte nicht mehr > reinschaun. > Danke dir Matthias! > > Ich bin in C++ nicht so bewandert (deswegen eben diese Fingerübung), > aber ist ein std::vector<char> nicht besser geeignet als ein > std::string? > Ich meine, über die Serielle werden ja auch Binärdaten übertragen. Im Prinzip hast Du recht, aber Nullbytes sind im Gegensatz zu C-"Strings" kein Problem und der Vorteil beim String ist, daß man ihn problemlos zum Debuggen mit Standard-I/O-Funktionen auf die Konsole oder in eine Datei schreiben kann. Das ist letztenendes Geschmackssache. > Ansonsten: > Ich habe vor längerer Zeit einen Bootloader (PC-Seite) für meine > AVR-Projekte geschrieben, in reinem C. > Als Übung wollte ich diesen nun auf C++ umschreiben. > Leider fallen mir hier einige Sachen auf die mich stören. > Allen vorran die Tatsache, dass ich in meinem Klassenheader > Informationen über die interne Umsetzung preisgeben muss (Stichwort: > private Attribute). Das mußt Du nicht, allerdings ist die Lösung etwas aufwendiger: 1. Basisklasse mit Header schreiben, die nur das im Header exportiert, was Du willst und virtuelle Methoden für die von außen sichtbare Funktionalität enthält. 2. "Interne" abgeleitete Klasse schreiben, die die weitere Funktionalität enthält. Es gibt übrigens keinen Grund, dafür eine separate Headerdatei oder Quellcodedatei zu schreiben. 3. "Factory"-Funktion oder -methode zum Erzeugen einer Instanz der Klassen schreiben (am besten "public static"-Klassenmethode in der Basisklasse; wenn die Basisklasse zusätzlich nur einen Konstruktor hat, der private ist, kann man die Klasse dann nur über die Factory-Methode instantiieren). Die Factory-Funktion liefert dann nicht eine Instanz der Basisklasse, sondern eine der abgeleiteten Klasse und die Features der abgeleiteten Klasse sind dann vor dem Aufrufer, der nur die Headerdatei mit der Basisklasse hat, verborgen. Eine Steigerungsmöglichkeit wäre, daß die Factory-Methode Instanzen verschiedener abgeleiteter Klassen zurückliefern kann abhängig von Parametern oder Einstellungen. > Und spätestens wenn ich mehrere Klassen habe die andere Klassen als > Attribut verwenden habe ich dermaßen viele Folge-Includes, dass die > "oberste" Kompiliereinheit über das halbe Projekt "Bescheid weis". > Das stößt mir bisl sauer auf, weil ich in C sehr darauf geachtet habe, > Interface (Header) und Implementierung (C-File) zu trennen... > > Ich werde das Projekt mal noch abschließen und danach neu beurteilen, ob > C++ das richtige für mich ist :-) Mal ganz im Ernst, ich bin kein C++-Fan, die Sprache ist furchtbar, aber es ist gegenüber C ein deutlicher Fortschritt, weil ich eine weitere Abstraktraktionsebene habe. Daß man Strings, diverse Containerklassen u. ä. hat, ist bei komplexeren Datenstrukturen ein großer Vorteil. Mit etwas Erfahrung geht das Meiste dreimal so schnell wie in C. Ich würde heute ohne Not (was bei Microcontrollern natürlich wegen Speicherbedarf einschl. Laufzeitumgebung gegeben sein kann) keine reinen C-Projekte mehr neu beginnen. Allerdings sind einige Features mit Vorsicht zu genießen, z. B. ist printf() usw. oft handlicher, wenn auch leider fehleranfälliger, als iostream. Tschüß, Matthias
Korrektur: Gutes Buch ist "Der C++ Programmierer" von Ulrich Breymann.
Mir sind die Workarounds ("pimpl idiom", "simple pointer") durchaus bekannt. Aber ich finde das irgendwie, nunja, nicht elegant. @ Matthias: ja, die STL und ihre Container sind schon was feines (wenn man denn erstmal nen Überblick hat). Und ja, iostreams find ich bei einer komplexen Ausgabe auch sehr umständlich. Wobei, in meinem Fall (serielle Verbindung) könnte man den <<-Operator wunderbar überladen und zur Ausgabe nutzen. Gruß, Karl
boost::asio kann auch mit seriellen Schnittstellen arbeiten... http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/overview/serial_ports.html
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.