Hallo UML

Die erste eigene Funktionalität die wir mit den Mitteln des PEC-Framework realisieren wollen sind kleine Experimente mit einer LED und einem Taste. Vorraussetzung ist, dass wir ein Projekt mit den PEC-Bibliotheken angelegt und ein Klassendiagramm mit dem Grundgerüst einer PEC-Anwendung erstellt haben. Falls Sie das noch nicht vorliegen haben sollten Sie sich gewissenhaft mit der Projektvorbereitung beschäftigen. Haben Sie SiSy bereits offen und ein aktuelles PEC-Projekt geladen dann können Sie nachher den Abschnitt Vorbereitung überspringen.

Die Aufgabe

Entwickeln Sie eine Mikrocontrolleranwendung bei der Sie zunächst eine LED ansteuern. Im zweiten Schritt soll die LED nur beim betätigen eines Tasters leuchten.

Theorie

Wir werden recht schnell beim Durchstöbern der PEC-Pakete fündig. Im Paket pec_Gpio findet sich neben anderen Bausteinen fertige Klassen und Templates um eine Led anzusteuern. In diesen Bausteinen sind all die mühseligen Kommandos für die Initialisierung eine Pins als Eingang oder Ausgang bereits gelöst und das auch noch portabel. Das bedeutet für den Entwickler, dass diese auch auf anderen Controllertypen verwendbar sind. Die meisten Bausteine können übrigens wesentlich mehr als wir für diese einfache Aufgabe brauchen. Das wird aber beim Übersetzen und bilden der Anwendung „weg optimiert“ falls Sie die Funktionalitäten nicht benutzt haben.

Mit etwas Übung im SiSy-Handling kann man sich elegant zum Quelldiagramm der Basisklasse durch hangeln. Dort ist dann das Klassendiagramm und der Quellcode der Bibliotheksklasse einseh- und ggf. auch abänderbar (Modell- und Quellcodeoffen). Wir werden das Template PecPinOutput verwenden.

Wir könnten diese einfachere Klasse benutzen, um einen simplen IO-Pin abzubilden. Das Framework bietet zwei Basisbausteine für ein Output-Pin. Zum einen ein Template um eigene Klassen mit den Eigenschaften eines Output-Pins auszustatten und zum anderen eine Klasse die sofort als Typ angewendet werden kann um Attribute oder andere Instanzen davon zu erzeugen.

Vorbereitung

Falls Sie jetzt kein SiSy mit einem frischen PEC-Projekt vorliegen haben sollten Sie das jetzt vorbereiten. Ansonsten überspringen Sie diesen Absatz.

(Mit installiertem Flash kann man an dieser Stelle ein Video in dieser Web-Seite ansehen.)

Lösungsansatz

Sie haben eine frische PEC aus dem LibStore geladen und ein Klassendiagramm für Ihr Systemboard angelegt und an die Zielplattform angepasst. Das so erstellte Klassendiagramm sieht in etwa wie folgt aus:

Wir halten kurz verbal fest was dieses Klassenmodell als Konstruktionszeichnung und Realisierungsvorschrift die vom Codegenerator umgesetzt wird festlegt:

  • es gibt eine Klasse Controller diese verfügt über die Operationen
    • onStart
    • onWork
  • Die Klasse Controller realisiert ein PecAppKernel
  • das Objekt app ist die Instanz der Klasse Controller
  • es werden die Pakete Pec und MCU_XXX_xxx verwendet

die Aufgabe besteht darin, die gewünschte LED auf dem Board blinken zu lassen um einen bestimmten Systemstatus zu signalisieren. Dazu benötigen wir im Klassenmodell den entsprechenden Baustein. Im folgenden wird eine von verschiedenen Möglichkeiten aufgezeigt wie der Systemdesinger einen benötigten Baustein in sein Klassenmodell aufnehmen kann. Dazu sind folgende Überlegungen vorausgegangen:

  • das System hat eine StatusLED
  • die StatusLED ist mit dem Controller über Port X Bit n verbunden
  • wenn das System instanziiert (angelegt und hochgefahren) wird soll die LED automatisch verfügbar sein
  • die LED ist solange verfügbar wie das System läuft

Diese Überlegungen führen zunächst dazu, dass der Systemdesigner sich dafür entscheidet die StatusLED als Attribut in der Klasse Controller zu aggregieren. Hierbei hat er auch wieder verschiedene Möglichkeit. Er entschließt sich eine Klasse mit dem namen StatusLED anzulegen und diese über einer Aggregationsbeziehung mit dem Controller zu verbinden. Dabei wird die Aggregation vom Codegenerator als Attribut der Klasse Controller abgebildet. Der Attributname wird als sogenannter Rollenbezeicher +statusLED an der Aggregationsbeziehung mit dessen Sichtbarkeit notiert. Beachten Sie die Unterscheidung in der Schreibweise zwischen dem Typ StatusLED und der Instanz statusLED.

Aus diesem Modell wird der Codegenerator vereinfacht dargestellt folgenden Quelltext für die Klassen Controller und StatusLED erstellen.

///////////////////////////////////////////////////////////
class Controller : public PecAppModul
{
  // Attribute
  public: StatusLED statusLED;
  // Operationen
  public: Controller();
  public: ~Controller();
  public: void onStart();
  public: void onWork();
};
 
///////////////////////////////////////////////////////////
class StatusLED
{
  // inline
  public: StatusLED()  { }  // Konstruktor
  public: ~StatusLED() { }  // Destruktor
};

Diese Vorgehensweise für die Abbildung eines Systembausteins im Klassenmodell kann für die Arbeit mit den PEC-Bibliotheken durchaus als typisch angesehen werden. Zusätzlich wird diese Variante der Modellierung durch das Angebot zahlreicher PEC-Templates gefördert. Es liegt jetzt am Systemdesigner, dem Architekten in Ihnen eine geeignete Basisklasse oder ein geeignetes Template aus den Bibliotheken herauszusuchen. In der folgenden Darstellung wird die Realisierung mit dem Template PecPinOutput gezeigt. Dabei ist zu beachten, dass der Teil aus den eigentlichen PEC-Paketen lediglich Festlegungen der Signatur der Klassen und Schnittstellen darstellt also portable und damit nicht spezifischen Code für Ihren Controller enthält. Diesen Umstand erkennen Sie am Präfix pec. Es ist notwendig zusätzlich controllerspezifische Informationen an die zu realisierende Klasse anzubinden. Das geschieht über die Zuweisung des betreffenden plattformspezifischen Pins.

Aus diesem Modell erstellt der Codegenerator wiederum den plattformspezifischen Code der im Folgenden vereinfacht abgebildet ist.

// Defines from Templates
#define PinOutput_HighActive
#define PinOutput_PushPull
#define PinOutput_NoPull
 
class StatusLED // implements PecDigitalOut
{
  // Attribute from PecDigitalOut
  protected: volatile port_t* port;
  protected: pinMask_t bitmask;
  // Operationen from PecDigitalOut
  public: virtual bool getState();
  public: void setState(bool newState);
  public: virtual void config(port_t port, pinMask_t bitmask);
  public: void on();
  public: void off();
  public: void toggle();
  // inline
  public: StatusLED() {config( PORTx, BITn );}
  public: ~StatusLED(){ }
};

Realisierung

Bis hier haben wir uns in der Adlerperspektive wir können auch sagen auf Architekturebene bewegt. Die Niederungen der Froschperspektive bleiben uns aber nicht ganz erspart. Da das Ganze alles andere als malen nach Zahlen ist sollten Sie sich darüber bewusst sein, dass es hier nach wie vor um native C++ Programmierung geht. Die grafische Arbeit sorgt lediglich dafür, dass wir eine andere Perspektive und gleichzeitig eine adäquate Dokumentation der Architektur des Systems haben. Das ganze müsste in einer klassischen IDE einfach vom Programmierer als Quelltext getippt werden. Das Quelltext tippen des Architekturrahmens übernimmt für uns der Codegenerator. Nicht mehr und nicht weniger. Über die konkrete Verarbeitungslogik entscheiden nach wie vor Sie in der Rolle des Programmierers. Hier eine einfache Lösung die StatusLED blinken zu lassen.

onWork
  statusLED.toggle();
  waitMs(300);

Wenn wir die zwei Zeilen richtig eingegeben und das Modell korrekt erstellt haben können wir aus dem Klassendiagramm den Quellcode generieren, diesen übersetzen und auf den Controller übertragen. Das erfolgt über das Aktionsmenü in der Objektbibliothek. Wählen sie dort den Menüpunkt Erstellen, Brennen & Ausführen.

"Intelligenter" Lichtschalter, EVA Eingabe, Verarbeitung, Ausgabe

Als nächsten Schritt erweitern wir unsere Firmware um die Funktionalität eines Tasters. Die StatusLED soll nur leuchten, wenn der Taster gedrückt ist. Folgende Vorüberlegungen stellt der Systemdesiner an:

  • das System hat einen Taster
  • der Taster ist mit dem Controller über Port X Bit n verbunden
  • der Taster benötigt ggf. einen PullUp
  • wenn das System instanziiert (angelegt und hochgefahren) wird soll der Taster automatisch verfügbar sein
  • der Taster ist über die gesamte Laufzeit des Systems verfügbar

Das kommt uns bekannt vor. Der Systemdesiner in uns entscheidet sich für die gleiche Vorgehensweise wie bei der StatusLED. Als geeignete Templates wählt er PecPinInput, PinPullUp und pinXn. Diese bindet er an die Aggregierte Klasse Taster.

Den Quellcode der Operation onWork ändern wir wie folgt:

onWork
  // Eingabe, Verarbeitung, Ausgabe
  if (taste.getState()==0)
  {
	statusLED.on();
  }
  else
  {
	statusLED.off();
  }

Test

haben wir das Modell und den Quellcode korrekt erstellt sollte das system nach dem Bilden und Übertragen wie gewünscht funktionieren.

Videozusammenfassung

Und hier diesen Abschnitt als kurze Videozusammenfassung.

Wählen Sie hier Ihren Mikrocontrollerfamilie aus:

AVR Mikrocontrollerfamilie SAM Mikrocontrollerfamilie STM Mikrocontrollerfamilie XMC Mikrocontrollerfamilie

Vertiefende Themen

Nächstes Thema

Wer mag kann sich jetzt ein wenig in den Bibliotheken umschauen

oder

hallo_uml.txt · Zuletzt geändert: 2015/11/12 15:43 von dokuwi13