Forum: Mikrocontroller und Digitale Elektronik Brauche Hilfe beim Abbilden der Registerstruktur eines am Arduino angeschlossenen ICs in C++


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Flunder (flunder)


Lesenswert?

Ich habe hier ein mit dem Arduino verbundenes IC. In dem gibt es 
Register, die ich lesen und schreiben kann. Jedes dieser Register hat 
eine Nummer (Adresse). Die Bits in den Registern haben natürlich jeweils 
ihre Bedeutung.

Jetzt wollte ich das in C++ abbilden. Eine Klasse, die die 
Gemeinsamkeiten aller Register darstellt. Dazu soll es 
Funktionen/Methoden geben, um den Registerwert ins IC zu schreiben und 
um ihn auszulesen. Denen will ich dann ein Objekt eines Erben dieser 
Klasse übergeben.

Von dieser Klasse müssen also andere Klassen erben.

Die Registeradresse soll öffentlich nur lesbar sein, da ja für jedes 
Register konstant. Sie ist bei jedem Erben anders.

Der Registerwert als Ganzes soll öffentlich les- und schreibbar sein.

Jeder Erbe soll zusätzlich noch Methoden bekommen, um einzelne Bits zu 
lesen und/oder zu setzen. Diese Methoden sollen nach der Bedeutung der 
Bits/Bitfelder im IC benannt sein. Sie lesen bzw. verändern erstmal den 
im Objekt gespeicherten Registerwert. Sprich man gibt, wenn nötig, vor 
deren Benutzung das Objekt an die Leseroutine und danach an die 
Schreibroutine, die ja alle Erben der Registerklasse schlucken können 
sollen. Diese Routinen sollen dann auf Registeradresse und Registerwert 
des Objekts zugreifen, um damit ihre Arbeit zu verrichten.

Erstmal hat der C++ Compiler meine Versuche ohne Warnungen oder gar 
Fehler geschluckt. Aber sobald ich ein Objekt eines Erben nur mal als 
Ahnen ablegen wollte, ging das Gemeckere los, dass er mir den Operator= 
gelöscht hätte, weil der ja doch nur Mist machen würde. Oder die Erben 
hatten die Registeradresse des Vorfahren übernommen. Wild verteilte 
"virtual" führten zu noch mehr Gemeckere beim Kompilieren.
1
class AS5X47_Register {
2
  public:
3
    const uint16_t addr = 0x0042U;
4
    uint16_t raw = 0U;
5
    uint16_t get_raw_value() const;
6
    void set_raw_value(uint16_t val);
7
    AS5X47_Register();
8
};
9
10
class AS5X47_Prog : public AS5X47_Register {
11
  public:
12
    const uint16_t addr = 0x0003U;
13
    uint_fast8_t get_prog_ver() const;
14
    void set_prog_ver(uint_fast8_t val);
15
16
    uint_fast8_t get_prog_otp() const;
17
    void set_prog_otp(uint_fast8_t val);
18
};

Kann mir von Euch jemand helfen, daraus gültigen und funktionierenden 
C++ - Code zu machen ?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Ich verstehe deinen Text nicht!

Vererbung:
class AS5X47_Prog : public AS5X47_Register

Ist eine "Ist ein" Beziehung.
Also: AS5X47_Prog ist ein AS5X47_Register
Ist der Satz so logisch korrekt?


Alternativ:
In C++ werden auch Schnittstellen so "vererbt"
Dann: AS5X47_Prog implementiert AS5X47_Register
Ist der Satz so logisch korrekt?

Wenn du beide Fragen verneinst, dann ist Vererbung der falsche Weg.

Flunder schrieb:
> uint16_t raw = 0U;
Das ist ein NoGo.
Öffentliche Instanzeigenschaften sollte man tunlichst vermeiden. Die 
Instanz kann die Gültigkeit nicht Überwachen bzw. sicherstellen.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Abgesehen von der berechtigten Diskussion, ob Vererbung hier überhaupt 
sinnvoll ist, steckt der Knackpunkt (der auch den default operator= 
verhindert) hier:
> const uint16_t addr = 0x0042U;

Da solltest du noch mal drüber nachdenken.

Oliver

von Oliver S. (oliverso)


Lesenswert?

Nachtrag: Darüber, wie sinnvoll ein operator= oder jede andere Art von 
Copy operator dabei ist, braucht man eigentlich auch nicht zu 
diskutieren. Register und ähnliches sind üblicherweise Highlander: es 
kann nur einen geben...

Oliver

: Bearbeitet durch User
von Flunder (flunder)


Lesenswert?

Arduino F. schrieb:
> Ich verstehe deinen Text nicht!
Entschuldigung, besser habe ich es nicht hin bekommen.
> Vererbung:
> class AS5X47_Prog : public AS5X47_Register
>
> Ist eine "Ist ein" Beziehung.
> Also: AS5X47_Prog ist ein AS5X47_Register
> Ist der Satz so logisch korrekt?
Ja Prog ist eines der Register.

> Alternativ:
> In C++ werden auch Schnittstellen so "vererbt"
> Dann: AS5X47_Prog implementiert AS5X47_Register
> Ist der Satz so logisch korrekt?
Eine Schnittstelle ist doch quasi eine Verpflichtung, dass meine Klasse 
vorgegebene Methoden/Eigenschaften implementiert ?
Das hatte ich jetzt nicht gewählt, da get_raw_value() und 
set_raw_value() eigentlich immer gleich sind.

> Wenn du beide Fragen verneinst, dann ist Vererbung der falsche Weg.
>
> Flunder schrieb:
>> uint16_t raw = 0U;
> Das ist ein NoGo.
> Öffentliche Instanzeigenschaften sollte man tunlichst vermeiden. Die
> Instanz kann die Gültigkeit nicht Überwachen bzw. sicherstellen.
Also auch nicht, wenn alle mit 16 Bit darstellbaren Werte an der Stelle 
zumindest einen Funken Sinn ergeben ?
Ok, wird nervig, wenn ich im Nachhinein beim Ändern noch eine Aktion 
beim Schreiben oder Lesen auslösen mag. Bei Delphi und C# konnte man da 
mit Eigenschaften noch was kitten, aber die kennt C++ ja nicht.

von Flunder (flunder)


Lesenswert?

Oliver S. schrieb:
> Nachtrag: Darüber, wie sinnvoll ein operator= oder jede andere Art von
> Copy operator dabei ist, braucht man eigentlich auch nicht zu
> diskutieren. Register und ähnliches sind üblicherweise Highlander: es
> kann nur einen geben...
>
> Oliver

Meine Sicht war eher : ich habe Superhelden, nämlich Highlander, Spider 
Man und Dark Wing Duck. Jeden der drei gibt es nur einmal, aber ihre 
Gemeinsamkeiten kann ich vorher schonmal an zentraler Stelle 
implementieren und dann beerben.

von Flunder (flunder)


Lesenswert?

Oliver S. schrieb:
> Abgesehen von der berechtigten Diskussion, ob Vererbung hier überhaupt
> sinnvoll ist, steckt der Knackpunkt (der auch den default operator=
> verhindert) hier:
>> const uint16_t addr = 0x0042U;
>
> Da solltest du noch mal drüber nachdenken.
>
> Oliver

Ok, jeder Erbe hat einen anderen aber für sich gleichbleibenden Wert an 
dieser Stelle. Ich habe es nicht geschafft, dass die Erben 
unterschiedliche Konstruktoren haben, in denen der Wert gesetzt wird.

von Oliver S. (oliverso)


Lesenswert?

Ein Konstruktor darf Parameter haben.

Oliver

von Harald (hasanus)


Lesenswert?

Flunder schrieb:
> Meine Sicht war eher : ich habe Superhelden, nämlich Highlander, Spider
> Man und Dark Wing Duck. Jeden der drei gibt es nur einmal, aber ihre
> Gemeinsamkeiten kann ich vorher schonmal an zentraler Stelle
> implementieren und dann beerben.

Diese Sichtweise ist korrekt, und Vererbung kann durchaus angebracht 
sein.
Dein Problem ist die Instanzierung, d. h. der Versuch mit Objekten zu 
arbeiten.

Dein chip hat nur genau eine Instanz dieses oder jenes Registers. Es 
gibt keine Kopien davon. Sehr wohl aber kann dein Programm mit 
verschiedenen Stände der darin enthaltenen Daten arbeiten.

Besser du baust die Vererbung / Komposition mit zumeist statischen 
Methoden auf. Konstruktoren aktiviert Du nur wenn es tatsächlich 
erforderlich ist. Neueres c++ erlaubt nontype - template - parameter, 
damit kannst du z.B. die Register - Adressen als unsigned int übergeben. 
Deine statischen ::get() / ::set() - Methoden arbeiten dann auf 
Instantiierungen der template (und nicht der Klasse).

von Mikro 7. (mikro77)


Lesenswert?

Flunder schrieb:
> Jetzt wollte ich das in C++ abbilden. Eine Klasse, die die
> Gemeinsamkeiten aller Register darstellt. Dazu soll es
> Funktionen/Methoden geben, um den Registerwert ins IC zu schreiben und
> um ihn auszulesen. Denen will ich dann ein Objekt eines Erben dieser
> Klasse übergeben.

Man muss nicht alles OOP machen. Soweit ich es verstehe ist das Lesen 
und Schreiben von Registern immer gleich; nur die Adresse unterscheidet 
sich. Das sind dann halt einfach zwei Funktionen. Da braucht man keine 
Vererbung.

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.