====== Hallo XMC-Welt in C++ und UML ====== So, dann frisch ans Werk. Die erste Übung mit der wahrscheinlich ungewohnten Umgebung soll wieder das einfache Einschalten einer LED sein. Der Sinn und Zweck von Klassenbibliotheken ist natürlich vor allen auch der, dass Dinge die öfters gebraucht werden oder typische Problemstellungen die einfach schon mal gelöst wurden, dem Anwender komfortabel zur Wiederverwendung zur Verfügung stehen. ===== Die Aufgabe ===== Die Objektorientierung zeichnet sich durch zunehmende Abstraktion von der tatsächlichen inneren Struktur und dem internen Verhalten der Maschine, hin zu einer anwenderbezogenen Sichtweise aus. Die Aufgabe lautet: //Entwickeln Sie eine Mikrocontrolleranwendung (Applikation) die eine LED anschaltet.// ===== Vorbereitung ===== Falls Sie jetzt noch das Klassendiagramm geöffnet haben wählen Sie im Kontextmenü (rechte Maustaste) des Diagramms den Menüpunkt nach oben. Falls das Projekt nicht mehr geöffnet ist, öffnen sie das SiSy UML-Projekt wieder. Legen Sie ein neues Klassendiagramm an und wählen Sie die Sprache //ARM C++//. Beachten Sie die Einstellungen für die Zielplattform //XMC4500 Relax Kit//. Beim Öffnen des Diagramms (rechte Maustaste, nach unten) laden Sie die Diagrammvorlage für eine //PEC Applikation// und weisen das Treiberpaket für den //XMC4500// zu. >>><html><iframe width="640" height="480" src="https://www.youtube.com/embed/-YRw0XvoNyQ" frameborder="0" allowfullscreen></iframe></html> ===== Lösungsansatz ===== Die Aufgabe besteht darin eine LED anzusteuern. Folgen wir der objektorientierten Sichtweise, ist die //Led// unser Klassenkandidat. Eine Klasse //Led// soll die spezifische Initialisierung und Programmierung eines GPIO Pin auf der Anwenderebene abstrahieren. Also fragen wir uns, was eine LED denn aus Anwendersicht so tut. Sie kann an oder aus sein, vielleicht blinkt sie ja auch. >>>{{:anwendersichtledan.jpg?400|}} Die Abbildung genau dieser Verhaltensmerkmale fordern wir von der Klasse //Led//. Sich mit //XMC_GPIO_OUTPUT_TYPE_PUSH_PULL// und //PORT1->OUT |= (1<<0)// herumzuschlagen ist mit Sicherheit wichtig, um zu erlernen, wie ARM Controller intern funktionieren und um ggf. eigene Klassen für die Erweiterung der Bibliothek zu realisieren. Aber es ist für die Lösung eines konkreten Anwendungsproblems eher zeitfressend und vielleicht sogar kontraproduktiv. Welcher GUI-Entwickler kümmert sich noch wie vor 25 Jahren von Hand um //[[http://msdn.microsoft.com/en-us/library/windows/desktop/ms644943(v=vs.85).aspx|Peek-]]//, //[[http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx|Get-]]//, //[[http://msdn.microsoft.com/en-us/library/windows/desktop/ms644955(v=vs.85).aspx|Translate-]]// und //[[http://msdn.microsoft.com/en-us/library/windows/desktop/ms644934(v=vs.85).aspx|DispatcheMessage]]//, nur weil es grundlegende und extrem wichtige Funktionen in einer grafischen Benutzeroberfläche sind. Er möchte eine konkrete Anwendung schreiben. Dazu reicht das Grundverständnis der Funktionsweise einer GUI und eine leistungsfähige Klassenbibliothek. Für die Ansteuerung von LEDs gibt es im SiSy PEC Framework fertige Klassen. Die Kunst besteht jetzt darin, sich diese zugänglich zu machen. In klassischen Entwicklungsumgebungen schaut man in die Hilfe, ins Lehrbuch oder in ein Tutorial, schreibt die Zeilen ab, die dort erklärt werden und darf unter Umständen nicht vergessen benötigte Pakete per //include//, //using// oder //import// einzubinden. In unserem Klassendiagramm ist die Bibliothek bereits eingebunden. Sie steckt in dem Ordner //Pec//. Das Suchen geeigneter Klassen in den Bibliotheken erfolgt in SiSy am besten über den Navigator. Öffnen Sie das Kontextmenü des Navigators mit der rechten Maustaste. Wählen sie den Menüpunkt //UML-Pakete// {{:navigartumschalten.png?365|}} . {{:umlpakete.png?380|}} Wir werden recht schnell beim Durchstöbern der Pakete fündig. Im Paket //pec_InOut// findet sich neben anderen Klassen eine fertige Klasse //Led//. In dieser sind all die mühseligen Kommandos für die Initialisierung bereits gelöst und das auch noch portabel. Das bedeutet für den Entwickler, dass diese Klasse auch auf einen anderen Controllertyp verwendbar ist. Die Klasse kann übrigens auch wesentlich mehr als wir für diese einfache Aufgabe brauchen. Mit etwas Übung im SiSy-Handling kann man sich elegant zum //Quelldiagramm// der Basisklasse durch hangeln, um sich all das anzuschauen. Dort sind das Klassendiagramm und der Quellcode der Bibliotheksklasse einseh- und ggf. auch änderbar (Modell- und Quellcodeoffen). >{{:ledbasisklasse.jpg?350|}} . {{:pinoutput.jpg?350|}} Wir könnten die eine einfachere Klasse benutzen, die einen simplen IO-Pin abbildet, aber was soll's ... nehmen wir die sexy Led. Dazu ziehen wir die Led aus dem Navigator per Drag & Drop in das Klassendiagramm. >{{:dragunddropled.png?330|}}{{:ledaggregieren.png?380|}} Wenn wir die Klasse //Led// hereingezogen haben, müssen wir diese mit der Anwendung verbinden. Vergleichen sie dazu die Ausführungen zur Aggregation im Grundlagenteil dieses Tutorials. Selektieren Sie dazu die Klasse //Controller//. Am unteren Rand erscheint eine große, rote Selektionsmarke. Das ist der //Verteiler//. Ziehen Sie von hier aus per Drag & Drop eine Verbindung von der Klasse //Controller// zur Klasse //Led//. Wählen Sie als Verbindungstyp die Aggregation und als Rollenbezeichner //+led//. Der Controller hat jetzt eine Led. Das ist dann unser Entwurf der Struktur unserer Anwendung in Form eines UML-Klassendiagramms. Die meisten UML-Werkzeuge bieten an dieser Stelle das Generieren der Klassenrümpfe, um diese dann in eine IDE einzufügen. Dort können dann die konkreten Verhaltensmerkmale der so entworfenen Klassen fertig programmiert und ggf. die Klassen angepasst oder erweitert werden. Damit stimmen Konstruktionszeichnung und Quellcode jedoch nicht mehr miteinander überein. Das ist wie der richtige Schaltplan zur falschen Schaltung oder umgekehrt. Für diesen Defekt gibt es manchmal die Möglichkeit, dass das UML-Tool sich wiederum mit den Quelltextänderungen synchronisiert. In SiSy bleiben wir im Klassendiagramm und realisieren hier auch gleich das System. ===== Realisierung ===== Der Entwurf sollte der folgenden Darstellung entsprechen: * die zentrale Klasse ist die //Controller// * diese verfügt über die Operationen //onStart// und //onWork// * Die Applikationsklasse //Controller// ist ein //PecAppKernel// * Das globale Objekt //app// ist die Instanz der Klasse //Controller// * Die Klasse //Controller// verfügt über eine //Led// mit dem Attributnamen //led// * Das Attribut //led// der Klasse Controller ist öffentlich >>>{{:umlhalloarm.jpg?700|}} Die Aufgabenstellung fordert, dass eine LED einzuschalten ist. Diese ist bekanntlich an Pin 1.0 angeschlossen. Für die Initialisierung von Geräten steht die Operation //onStart// zur Verfügung. Selektieren Sie diese Operation und geben im Quelltexteditor folgenden Code ein: **Controller::onStart:** >>><code cpp> led.config(PORT1,BIT0); </code> Beobachten Sie gleichzeitig das rechts neben dem Quelltexteditor befindliche Sequenzdiagramm. Dies wird automatisch aus dem von Ihnen eingegebenen Code erzeugt. Das Sequenzdiagramm kann zum einen für Dokumentationszwecke genutzt werden zum anderen soll es gleichzeitig als Review für den Quellcode dienen. >>>{{:ledconfig.jpg?350|}} Selektieren sie danach die Operation //onWork// und geben den folgenden Code ein: **Controller::onWork:** >>><code cpp> led.on(); </code> >>>{{:ledon.jpg?350|}} ===== Test ===== Übersetzen Sie das Programm. Korrigieren Sie ggf. Schreibfehler. Übertragen Sie das lauffähige Programm in den Programmspeicher des Controllers. - Erstellen (Kompilieren und Linken) - Brennen >{{:erstellenbrennen.png?300|}}{{:blaueled.jpg?350|}} ====== Videozusammenfassung ====== Erlernte und gefestigte Arbeitsschritte: - //Klassendiagramm// anlegen und öffnen - Diagrammvorlage für eine //PEC Applikation// auswählen laden und Treiberpaket für den XMC4500 einfügen - Navigator auf //UML Pakete// umschalten - gewünschte Klasse //Led// im Navigator suchen und ins Diagramm ziehen - Klassen //aggregieren// - den nötigen //Quellcode// in den Operationen eintragen - //Erstellen und Brennen// eine XMC Applikation im Klassendiagramm Und weil es so schön war hier das Ganze noch mal als Video. >>><html><iframe width="640" height="480" src="https://www.youtube.com/embed/-EhQzVnbfug" frameborder="0" allowfullscreen></iframe></html> ====== Übung ====== Erweitern Sie zur Übung zum Blinky-Beispiel. Beachten Sie, dass Sie keine eigene //Mainloop// aufbauen müssen sonderen dass die Operation //onWork// aus der bereits realisierten Mainloop im PecAppKernel getriggert wird! ====== Nächstes Thema ====== * [[Button und LED|Mit den Klassen Button und LED weiter arbeiten]]