FSST - Hardwarenahe Programmierung
HasA
HasA versus IsA¶
Composition (Komposition, Aggregation): Beschreibt die Beziehung zwischen einem Ganzen und seinen Teilen.
Das folgende UML Klassendiagramm zeigt die Klasse HasA, wobei die Klasse DigitalOut instanziiert wird (Klasse HasA hat ein DigitalOut-Element):
Dieses UML-Diagramm der Klasse HasA wird in den folgenden C++ Code umgesetzt:
class HasA { private: DigitalOut _led; public: HasA(PinName ld) : _led(ld) {}; // Constructor void LedOn() { _led = 1; } void LedOff(){ _led.write(0); } };
- In Zeile 4 wird eine private Membervariable (Attribut) _led des Datentypes DigitalOut der Klasse HasA hinzugefügt.
- In Zeile 7 wird ein parametrisierter Konstruktor verwendet und die private Membervariable _led mit dem übergebenen Parameter Pin ld initialisiert. - Für den C++ Compiler liest sich diese Zeile folgendermaßen: "Erzeuge das Element _led mit Hilfe des Arguments ld des HasA-Konstruktors.
Die Initialisierung der Elemente (lokale Variablen) des parametrisierten Konstruktors mit dem aktuelle Wert (Argument) erfolgt über eine Initialisierungsliste, was eine wesentliche Vereinfachung ist. - In Zeile 8 und 11 werden zwei Methoden (Memberfunktionen, Elementfunktionen) inline Implementiert.
- Zeile 9 verwendet eine Abkürzung zur write-Methode in Zeile 12 den überladenen = Operator zum Einschalten der Led
- Zeile 12 verwendet die write-Methode.
Das Blinky-Programm sieht wie folgt aus:
int main() { HasA myLed1(LED1); while(1) { myLed1.LedOn(); wait(0.5); myLed1.LedOff(); wait(0.5); } }
- In Zeile 2 wird das Objekt myLed1 mit der LED1 instanziiert.
- In Zeile 4 und 6 erfolgen die Aufrufe der Methoden des Objekts myLed1 der Klasse HasA
Aufgabe Pwm¶
Schreiben Sie nach obigem Muster eine Klasse HasPwm die anstelle der DigitalOut-Klasse die PwmOut-Klassse instanziiert, wobei die Methode LedOn in einer for-Schleife alle 200ms den Wert auf die _led von 0.0 auf 1.0 erhöht (dimmt dunkler). Testen Sie Ihre Klasse, indem Sie in main() ein Objekt redRgb erzeugen und die rote RGB-Led dimmen.
Lösung?
Alternative Zeiger¶
Alternativ kann eine Membervariable (Attribut) des Datentypes DigitalOut als Zeigervariable hinzugefügt werden. Allerdings wird erst die Adresse des eigentlichen Zieles - auf eine Klasse DigitalOut – erzeugt und im parametrisierten Konstruktor - selber Name wie Klasse - mit einem Pin-Namen als Parameter wird das neue DigitalOut Objekt led1 mit Pin ld1 erzeugt:
class HasA // composition { private: DigitalOut *_led; public: HasA(PinName ld) : _led(&DigitalOut(ld)){ }; void LedOn() { _led->write(1); } void LedOff(){ (*_led).write(0); } };
Methode: Der Aufruf der Methode write() in der Klasse DigitalOut erfolgt über den Zeiger _led entweder mit direktem Zugriff mit „.“ (*_led).write(0) – Klammern wegen der Operator Priorität C++ Operator Precedence oder besser indirekter Zugriff über den Zeigeroperator „->“ Zeiger auf Element:
void LedOn() { led1->write(1); }
Im Blinky-Programm bleibt alles gleich wie oben.
Anmerkung: Der Compiler erzeugt für beide Varianten den gleichen Assembler- bzw. Objektcode.