Ich suche nach C ++ - Abstraktionen für Hardware-E / A-Punkte oder -Pins. Dinge wie in_pin, out_pin, inout_pin, vielleicht open_collector_pin, etc.
Ich kann mir mit Sicherheit selbst eine solche Sammlung von Abstraktionen einfallen lassen, also suche ich nicht nach Antworten wie "Hey, vielleicht machst du das so", sondern nach dem "Blick auf diese Bibliothek, die in diesem und jenem und jenem verwendet wurde dieses Projekt'.
Google hat nichts aufgedeckt, vielleicht weil ich nicht weiß, wie andere das nennen würden.
Mein Ziel ist es, E / A-Bibliotheken zu erstellen, die auf solchen Punkten basieren, aber auch solche Punkte bereitstellen, sodass es beispielsweise einfach ist, eine HD44780 LCd entweder an die E / A-Pins des Chips oder an einen I2C (oder SPI) anzuschließen. I / O-Extender oder jeder andere Punkt, der irgendwie gesteuert werden kann, ohne die LCD-Klasse zu ändern.
Ich weiß, dass dies auf dem neuesten Stand der Elektronik / Software ist. Tut mir leid, wenn es nicht hierher gehört.
@leon: Verkabelung Das ist eine große Tüte Software, die ich mir genauer ansehen muss. Aber es scheint, dass sie keine Stecknadelabstraktion verwenden, wie ich es will. Zum Beispiel in der Tastatur-Implementierung sehe ich
digitalWrite(columnPins[c], LOW); // Activate the current column.
Dies impliziert, dass es eine Funktion (digitalWrite) gibt, die weiß, wie auf einen E / A-Pin geschrieben wird. Dies macht es unmöglich, einen neuen Typ von I / O-Pin hinzuzufügen (zum Beispiel einen, der sich auf einem MCP23017 befindet, so dass er über I2C geschrieben werden muss), ohne die digitalWrite-Funktion neu zu schreiben.
@Oli: Ich habe ein Arduino IO-Beispiel gegoogelt, aber die scheinen ungefähr den gleichen Ansatz wie die Wiring-Bibliothek zu verwenden:
int ledPin = 13; // LED connected to digital pin 13
void setup(){
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
quelle
Antworten:
Kurze Antwort: Leider gibt es keine Bibliothek, in der Sie tun können, was Sie wollen. Ich habe es selbst schon oft gemacht, aber immer in Nicht-Open-Source-Projekten. Ich überlege, etwas auf Github zu bringen, bin mir aber nicht sicher, wann ich kann.
Warum C ++?
quelle
Gestatten Sie mir, mein Open-Source-Projekt https://Kvasir.io unverschämt einzustecken . Der Kvasir :: Io-Teil bietet Stiftmanipulationsfunktionen. Sie müssen zuerst Ihren Pin mit einem Kvasir :: Io :: PinLocation wie folgt definieren:
Beachten Sie, dass dies nicht wirklich RAM verwendet, da es sich um Constexpr-Variablen handelt.
In Ihrem gesamten Code können Sie diese Pin-Positionen in 'Action Factory'-Funktionen wie makeOpenDrain, set, clear, makeOutput usw. verwenden. Eine 'Action Factory' führt die Aktion nicht aus, sondern gibt eine Kvasir :: Register :: Action zurück, die mit Kvasir :: Register :: apply () ausgeführt werden kann. Der Grund dafür ist, dass apply () die Aktionen zusammenführt, die ihm übergeben werden, wenn sie auf ein und dasselbe Register angewendet werden, sodass ein Effizienzgewinn erzielt wird.
Da die Erstellung und Zusammenführung von Aktionen zur Kompilierungszeit erfolgt, sollte dies denselben Assembler-Code ergeben wie das typische handcodierte Äquivalent:
quelle
Das Wiring-Projekt verwendet die folgende Abstraktion:
http://wiring.org.co/
und der Compiler ist in C ++ geschrieben. Sie sollten viele Beispiele im Quellcode finden. Die Arduino-Software basiert auf Wiring.
quelle
In C ++ ist es möglich, eine Klasse zu schreiben, sodass Sie E / A-Ports so verwenden können, als wären sie Variablen, z
ohne Rücksicht auf die zugrunde liegende Implementierung. Wenn Sie beispielsweise eine Hardware-Plattform verwenden, die keine Operationen auf Bitebene unterstützt, aber Registeroperationen auf Byteebene unterstützt, können Sie (möglicherweise mithilfe einiger Makros) eine statische Klasse IO_PORTS mit Inline-Lese- / Schreibzugriff definieren Eigenschaften mit den Namen bbRB3 und bbLATB4, sodass die letzte obige Anweisung zu wird
was wiederum in etwas verarbeitet werden würde:
Ein Compiler sollte in der Lage sein, den konstanten Ausdruck im?: -Operator zu erkennen und einfach den "wahren" Teil einzuschließen. Möglicherweise können Sie die Anzahl der erstellten Eigenschaften verringern, indem Sie die Makros folgendermaßen erweitern:
oder
Ich bin mir aber nicht sicher, ob ein Compiler den Code so gut in die Zeile schreiben kann.
Ich möchte keinesfalls implizieren, dass die Verwendung von E / A-Ports als Variablen zwangsläufig eine gute Idee ist, aber da Sie C ++ erwähnen, ist es ein nützlicher Trick, dies zu wissen. Meine eigene Präferenz in C oder C ++, wenn Kompatibilität mit Code, der den oben genannten Stil verwendet, nicht erforderlich wäre, wäre wahrscheinlich, für jedes E / A-Bit einen Makrotyp zu definieren und dann Makros für "readBit", "writeBit" zu definieren. "setBit" und "clearBit" mit der Maßgabe, dass das an diese Makros übergebene bitidentifizierende Argument der Name eines E / A-Ports sein muss, der für die Verwendung mit solchen Makros vorgesehen ist. Das obige Beispiel würde zum Beispiel geschrieben werden als
und übersetzt als
Das wäre für den Präprozessor etwas mehr Arbeit als für den C ++ - Stil, aber für den Compiler weniger. Es würde auch eine optimale Codeerzeugung für viele E / A-Implementierungen und eine angemessene Codeimplementierung für fast alle ermöglichen.
quelle
Wenn Sie nach etwas wirklich Tollem suchen, um die Hardware zu abstrahieren, und sich auf Ihre C ++ - Fähigkeiten verlassen können, sollten Sie dieses Muster ausprobieren:
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Ich habe es in einem Versuch verwendet, um Hardware für einen Cortex-M0-Chip zu abstrahieren. Ich habe noch nichts über diese Erfahrung geschrieben (ich werde es eines Tages tun), aber glauben Sie mir, es war sehr nützlich wegen seiner statischen polymorphen Natur: die gleiche Methode für verschiedene Chips, ohne Kosten (verglichen mit dynamischem Polymorphismus).
quelle