Forum: Mikrocontroller und Digitale Elektronik STM32 C++ Application Klasse Initialisierung Objekte


von muuuhhh (Gast)


Lesenswert?

Guten Morgen,

für einen STM32F3 möchte ich mein Programm in C++ schreiben. Dazu möchte 
ich eine Klasse Application als globales Singleton implementieren, in 
der alle Variablen und Objekte, die von dem Programm verwendetet werden 
enthalten sind. Mein Problem ist, wie gestaltet man die Initialisierung 
der Objekte? Beim Anlegen der eines Objekts von Application werden 
automatisch die Konstruktoren der Members aufgerufen.
Eigentlich möchte ich den Konstruktor der jeweiligen Klassen dazu 
verwenden, die Initialisierung durchzuführen.
Ich hätte zwei Ansätze zur Lösung meines Problems.

1. Alle Members von Application als Pointer deklarieren und im 
Konstruktor bzw. in einer initializeApplication()-Funktion als static 
anlegen und initialisieren um sie dann den Pointern zuzuweisen.

2. Jede Klasse erhält eine Funktion initialize(...) mit der die 
Initialisierung durchgeführt wird. So könnte ich den Zeitpunkt der 
Initialisierung von der Erstellung des Objekts unabhängig machen.

Gibt es auch andere Möglichkeiten das zu lösen?

Viele Grüße

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Moin,

das kommt darauf an was du erreichen willst. Bei Variante 1 werden die 
Konstruktoren in der Reihenfolge der statischen Definitionen der Objekte 
ausgeführt. Falls eines der Objekte eine Peripherie behandelt ist es 
meißt ungünstig wenn die eine Peripherie vor der einer Anderen 
initialisiert wird.
PWM vor dem CLOCK oder so.

Was bezweckst du mit dem Entwurf als Singleton? Aus Spaß an der Freude?
Bei einzigartigen Peripherieteilen macht ein Singleton für die 
Handlingklasse dieser Peripherie Sinn aber für die Application? Die ist 
doch schon im Controller gekapselt :).

Beschreib mal das Design was du im Kopf hast etwas genauer.

Gruß

Tec

von Rolf M. (rmagnus)


Lesenswert?

Tec N. schrieb:
> Was bezweckst du mit dem Entwurf als Singleton? Aus Spaß an der Freude?
> Bei einzigartigen Peripherieteilen macht ein Singleton für die
> Handlingklasse dieser Peripherie Sinn aber für die Application? Die ist
> doch schon im Controller gekapselt :).

Meist wird einem ja eingeredet, wie böse globale Variablen sind. Da 
kommt so ein Singleton gerade recht, um das gute Gefühl zu bekommen, 
diese vermieden zu haben. Man hat zwar keinen wirklichen Vorteil davon, 
aber immerhin die Regel beachtet.

von Jay (Gast)


Lesenswert?

Also syntaktischer Zucker um globale Variablen zu verbergen, die 
trotzdem faktisch nur globalen Variablen bleiben - auf die man nur etwas 
komplizierter zugreifen muss. Wer's mag ...

von Cyblord -. (cyblord)


Lesenswert?

Jay schrieb:
> Also syntaktischer Zucker um globale Variablen zu verbergen, die
> trotzdem faktisch nur globalen Variablen bleiben - auf die man nur etwas
> komplizierter zugreifen muss. Wer's mag ...

Das ist halt das typische Vorgehen wenn jemand OOP einsetzen will ohne 
OOP verstanden zu haben. Evt. rührt daher auch der vielerorts schlechte 
Ruf von OOP.

von muuuhhh (Gast)


Angehängte Dateien:

Lesenswert?

Tec N. schrieb:
> Was bezweckst du mit dem Entwurf als Singleton?

Mit dem Singleton möchte ich verhindern, dass mehrere Instanzen von 
Application erzeugt werden können (ich kann zwar bestimmen wie viele 
Objekte von Application in der main.cpp angelegt werden, aber ich dachte 
mir, so ist es "sauberer" programmiert). Wie würdet Ihr das machen?

Tec N. schrieb:
> Beschreib mal das Design was du im Kopf hast etwas genauer.

Puuuhh, also...
Das ganze wird ein bi-direktionaler Tiefsetzsteller (Aufbau als 
4-Quadrantensteller) für meine BA (Elektrotechnik).
Die Idee ist, die STM32 HAL-Treiber in Interfaces zu kapseln, die noch 
"relativ" generisch sind (ist alles ausbaufähig, aber dazu fehlt mir in 
der BA die Zeit). Daraus wiederum leite ich dann die spezifischen 
Hardware-Klassen ab, die ich zur Konfiguration und Steuerung der 
Peripherie verwende. Zusätzlich gibt es dann noch eine Klasse für die 
Tiefsetzsteller- bzw. DC/DC-Wandler Funktionalität. Im Anhang siehst 
Du/seht Ihr, wie mein Klassendiagramm bisher aussieht (bitte nicht 
schlagen, ich bin SEHR neu im Gebiet der Objekt orientierten 
Programmierung, das Wort Klassendiagramm gehört erst seit ein paar 
Wochen zu meinem Wortschatz ;)). Viele der Klassen sind noch nicht 
fertig. Aber ich hoffe man kann daraus die Richtung in die das Ganze 
gehen soll erkennen.

Viele Grüße und danke für die schnellen Antworten :)

von ui (Gast)


Lesenswert?

muuuhhh schrieb:
> Mit dem Singleton möchte ich verhindern, dass mehrere Instanzen von
> Application erzeugt werden können (ich kann zwar bestimmen wie viele
> Objekte von Application in der main.cpp angelegt werden, aber ich dachte
> mir, so ist es "sauberer" programmiert). Wie würdet Ihr das machen?

das kannst du doch auch verhindern wenn du das einfach programmierst, 
ohne zusätzliche Klasse "Applikation". Indem es nur eine Instanz davon 
gibt. Oder glaubst du, dass du dynamisch irgendwelche Dinge erzeugen 
willst?...

muuuhhh schrieb:
> Puuuhh, also...
> Das ganze wird ein bi-direktionaler Tiefsetzsteller (Aufbau als
> 4-Quadrantensteller) für meine BA (Elektrotechnik).
> Die Idee ist, die STM32 HAL-Treiber in Interfaces zu kapseln, die noch
> "relativ" generisch sind (ist alles ausbaufähig, aber dazu fehlt mir in
> der BA die Zeit). Daraus wiederum leite ich dann die spezifischen
> Hardware-Klassen ab, die ich zur Konfiguration und Steuerung der
> Peripherie verwende. Zusätzlich gibt es dann noch eine Klasse für die
> Tiefsetzsteller- bzw. DC/DC-Wandler Funktionalität. Im Anhang siehst
> Du/seht Ihr, wie mein Klassendiagramm bisher aussieht (bitte nicht
> schlagen, ich bin SEHR neu im Gebiet der Objekt orientierten
> Programmierung, das Wort Klassendiagramm gehört erst seit ein paar
> Wochen zu meinem Wortschatz ;)). Viele der Klassen sind noch nicht
> fertig. Aber ich hoffe man kann daraus die Richtung in die das Ganze
> gehen soll erkennen.

Prinzipiell sieht dein Klassendiagramm nicht schlecht aus.
Du musst aber aufpassen. Klassen auf nem µC haben manchmal ein unschönes 
Verhalten(implizite Aufruftiefe von Funktionen, Vererbung etc.). Da 
übersieht man recht schnell Dinge, was sich dann in der Geschwindigkeit 
der Applikation wiederspiegelt.

Ich persönlich würde es so nicht machen. Ich würde das nicht extra in 
die Klasse Applikation hineinkapseln, das wirkt doch sehr nach 
Selbstzweck und nicht nach dem Ansatz, den man eher IMHO verfolgen 
sollte: OOP dort wo's Sinn macht und dir wirklich einen Vorteil schafft.
Man kann auch ohne C++ Architekturen schaffen die funktionieren 
(Autosar).

Vererbung würde ich versuchen ganz raus zu lassen. Das kostet dich 
Laufzeit, welche aber u.U. nicht relevant ist(das kannst nur du 
einschätzen).

Ich hab bis jetzt nur die STD_Peripheral von STM genutzt, die ist ja 
eigentlich bereits vernünftig in "Objekte" gekapselt, auch wenn man dort 
nicht sowas schönes wie Überladung zur Verfügung hat.

Beim CAN: wenn du z.B. nur einen CAN zur Verfügung hast (bzw. nutzt) 
macht es in C++ manchmal Sinn, die Klasse zwar zur Verfügung zu haben, 
aber anstatt Instanzen davon zu erzeugen (nähmlich genau 1), die 
Funktionen und Variablen static zu deklarieren. Spart dir auch 
Initialisierungsarbeit.

muuuhhh schrieb:
> (bitte nicht
> schlagen, ich bin SEHR neu im Gebiet der Objekt orientierten
> Programmierung, das Wort Klassendiagramm gehört erst seit ein paar
> Wochen zu meinem Wortschatz ;))

Das versteh ich nicht ganz. Ist das eine explizite Anforderung an deine 
BA? In der BA soll man doch eigentlich das im Studium erlernte 
selbstständig umsetzen und dabei zeigen, wie gut man diese umsetzen 
kann. Wenn du im ganzen Studium noch nichts von Klassen gehört hast 
(bzw. OOP), warum muss du dann unbedingt alles OOP machen? Dein Problem 
kann man genauso gut in C lösen, dort kann man auch vernünftig arbeiten.

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Ich kann ui nur zustimmen.

Mit dem OOP halte ich das so, dass ich doppelten Code vermeide. Dann ist 
man oft an den sinnvollen Stellen gezwungen OOP einzusetzen.

von Peter II (Gast)


Lesenswert?

Tec N. schrieb:
> Mit dem OOP halte ich das so, dass ich doppelten Code vermeide. Dann ist
> man oft an den sinnvollen Stellen gezwungen OOP einzusetzen.

wie kann man denn mit OOP doppelte Code Vermeiden, was bei normalen 
Prozeduren nicht geht?

von Cyblord -. (cyblord)


Lesenswert?

Peter II schrieb:
> Tec N. schrieb:
>> Mit dem OOP halte ich das so, dass ich doppelten Code vermeide. Dann ist
>> man oft an den sinnvollen Stellen gezwungen OOP einzusetzen.
>
> wie kann man denn mit OOP doppelte Code Vermeiden, was bei normalen
> Prozeduren nicht geht?

Doofe Frage, sorry. Du kannst jedes OOP Konzept auch irgendwie ohne 
explizite OOP Unterstützung nachprogrammieren. Das ist ja wohl ein alter 
Hut.

von ui (Gast)


Lesenswert?

Peter II schrieb:
> wie kann man denn mit OOP doppelte Code Vermeiden, was bei normalen
> Prozeduren nicht geht?

speziell C++ vs. C? Dann Überladung. Vielleicht meinte er das auch.

muuuhhh schrieb:
> Viele der Klassen sind noch nicht
> fertig. Aber ich hoffe man kann daraus die Richtung in die das Ganze
> gehen soll erkennen.

Warum gibt es denn bitte 2 Klassen für das ADC Interface.
Du hast 1 Klasse ADC Interface, erzeugst aber während der 
Programmausführung 2 Instanzen davon (mit C++14 kann man das auch zur 
Kompilierzeit machen, dann muss das ganze aber statisch sein, könnte 
evtl. für dich was sein)

von ui (Gast)


Lesenswert?

muuuhhh schrieb:
> Im Anhang siehst
> Du/seht Ihr, wie mein Klassendiagramm bisher aussieht (bitte nicht
> schlagen, ich bin SEHR neu im Gebiet der Objekt orientierten
> Programmierung, das Wort Klassendiagramm gehört erst seit ein paar
> Wochen zu meinem Wortschatz ;)).

nochwas: Als Buchempfehlung (fande ich besser als unsere SE VL, und ich 
hab Informatik studiert): UML 2 Glasklar (ohne Werbung machen zu 
wollen).

Für dich ist es (vermutlich, sollte eigentlich dein Betreuer dir sagen, 
darauf hinweisen), wenn du dir nur ein grobes Klassendiagramm aufmalst. 
Muss auch nicht formal oder so sein, da gehts eher um das, das du weißt 
was wo ist. In deine BA kannst das Riesending mit allen Methoden etc. eh 
nicht reinpacken. Dort ist auch nur eine Übersicht Sinnvoll (welche 
Klassen gibt es und wie hängen die zusammen). Außerdem noch so ein 
grobes Architekturbild, wo nochmal ersichtlich ist, wo die verschiedenen 
Schichten sind, wie diese zusammenhängen. Versinnbildlicht (IMHO) den 
Zusammenhang und die Kapselung oft besser (Klasse A darf auf B 
zugreifen, die auf C zugreift. Aber A darf nicht auf C zugreifen z.B.).

Solange du keinen Code aus deinem Diagramm erzeugen willst macht es 
wenig Sinn, das so detailiert zu machen.

Oftmals sind Datenfluss bzw. Kontrollflussgraphen, Activitydiagramme, 
Sequenzdiagramme und Kommunikationsdiagramme (evtl. wirklich was für 
dich, nutzt ja auch CAN etc.) sinnvoll, die sind oftmals für den Leser 
interessanter als Klassendiagramme, weil man einfach schneller besser 
abschätzen kann, was passiert in welchem Zusammenhang und wie passsiert 
das.
Als Tipp ;)

von Jay (Gast)


Lesenswert?

muuuhhh schrieb:
> Mit dem Singleton möchte ich verhindern, dass mehrere Instanzen von
> Application erzeugt werden können (ich kann zwar bestimmen wie viele
> Objekte von Application in der main.cpp angelegt werden, aber ich dachte
> mir, so ist es "sauberer" programmiert).

Und welche böse Mann soll sich Nachts an deinen Computer schleichen und 
heimlich Code zu deinem Quelltext hinzufügen, so dass eine weiter 
Instanz von Application erzeugt wird?

von muuuhhh (Gast)


Lesenswert?

> Oder glaubst du, dass du dynamisch irgendwelche Dinge erzeugen
> willst?...
Das möchte ich eigentlich nach Möglichkeit vermeiden.



> Ist das eine explizite Anforderung an deine
> BA?

Nein. Ich wollte das lernen. Einen anderen Grund hat es eigentlich 
nicht.

Ich fand den Ansatz schön, dass man sich mit Interfaces eine Art 
Standard HAL schafft, die von der Plattform unabhängig wird. Damit wäre 
mein Programm auch auf anderen Controllern mit ARM Architektur 
lauffähig. Dazu müsste man natürlich Gemeinsamkeiten von allen 
Mikrocontrollern bzw. in meinem Fall ARM Cortex-M4F Controllern und 
deren Periphere herausfinden und diese jeweils für die virtuellen 
Funktionen des Interfaces umsetzen.

> Vererbung würde ich versuchen ganz raus zu lassen. Das kostet dich
> Laufzeit, welche aber u.U. nicht relevant ist(das kannst nur du
> einschätzen).
Wieso ist das so? Ich weiß leider nicht genau, wie der Compiler das 
umsetzt bzw. was dann während der Laufzeit des Programms passiert. Geht 
es dabei um die virtuellen Funktionen?

von BT (Gast)


Lesenswert?

schau mal wie die das so machen... gibt auch irgendwo ne demo von dem 
uml-tool...

http://mystm32.de/doku.php

Gruß

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
Noch kein Account? Hier anmelden.