Hallo Community,
ich möchte bei einem Mikrocontroller mittels einer Funktion einige
Register ansprechen. Z.B. C1CTRL und C2CTRL. Jetzt möchte ich aber nicht
eine funktion für C1CTRL und eine Funktion für C2CTRL schreiben, sondern
eine mit Übergabeparameter welches Register ich ansprechen möchte.
Geht das? Wie setzt ich das zusammen das z.B. der Übergabeparameter
nicht als "Name" gesehen wird.
Gruß Dirk
Beispiel:
bla (wert)
{
CwertCTRL = 0x1;
}
Wert kann 1 oder 2 sein
Gast
#4247756
In der Regel hast du eine Headerdatei mit defines, sprich du schreibst zwar den Namen als Parameter, es ist aber letztendlich in der Regel eine Zahl bzw. die Adresse des Registers.
Gast
#4247767
Praktisch schaust Du einfach mal nach, wie Identifier wie C1CTRL letztlich deklariert und definiert sind. Das kann unter Umständen über mehrere Preprozessor Makros und weitere C-Konstruktionen gehen. Wenn aber für den fraglichen uC der Compiler Ausdrücke mit C1CTRL als L-Wert akzeptiert muss am Ende gerade ein Typ herauskommen der als L-Wert geeignet ist. Manchmal ist das ein wenig verwickelt, weil noch Hilfsdefinitionen von Makros oder Typen eine Rolle spielen können. CMSIS ist so ein Beispiel. Aber für nen AVR führt die Suche ziemlich schnell zum Ziel. Der Typ ist dann auch der Parameter für die Funktion.
Dirk P. schrieb: > bla (wert) > { > CwertCTRL = 0x1; > } Hast du die letzten Jahrzehnte verpennt? K&R Deklarationen sind seid einem Vierteljahrhundert veraltet.
Mit einer für GCC spezifischen Erweiterung geht das u.U. auch ohne Blick auf das Register:
1 | |
2 | |
3 | |
4 | |
und Aufruf per
1 | |
Mal vorausgesetzt, die haben beide den gleichen Typ.
Das verstehe ich nicht ganz. Und wie ändere ich jetzt das je nach Übergabeparameter das C1 oder C2 Register anspreche?
Gast
#4247819
In dem Du die Funktion mit einem Parameter deklarierst, der dem Typ von C1CTRL entspricht. Dieser Funktion kannst Du dann "C1CTRL" als Wert übergeben. Nimm an, C1CTRL sei als char * deklariert. Dann wäre die Funktion:
1 | |
2 | |
3 | |
4 | |
Ahhh danke :)
Üblicherweise sind solche Registersymbole als "volatile" definiert, und benutzen irgendeine Compiler-spezifische Magie, um sie an eine feste Adresse zu legen:
1 | |
Für deinen Zeiger brauchst du die Adresse nicht, aber das "volatile" (oder was dort halt benutzt wird):
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Dirk P. schrieb: > > bla (wert) > { > CwertCTRL = 0x1; > } > > Wert kann 1 oder 2 sein Und was gefällt dir jetzt an
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
nicht? Nein. Du kannst nicht einen Variablennamen zur Laufzeit zusammen setzen lassen. Wenn das Programm läuft, existierten Variablennamen nicht mehr. Normalerweise ist der Versuch so etwas machen zu wollen, ein starker Hinweis darauf, dass man eigentlich ein Array einsetzen will
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Dirk P. schrieb: > Und wie ändere ich jetzt das je nach Übergabeparameter das C1 oder C2 > Register anspreche? bla(&C1CTRL); bla(&C2CTRL); Je nach µC gibt es in den Headern statt vieler Einzelregister (z.B. AVR) oft Strukturen für die I/O-Module (z.B: ARM). Dann geht das z.B. so void initUART(UART_REG_BLOCK *ptr) { ptr->CTRL1 = ...; ptr->STATUS = ...; } und ruft das so auf initUART(&UART1); initUART(&UART2);
Karl H. schrieb: > Normalerweise ist der Versuch so etwas machen zu wollen, ein starker > Hinweis darauf, dass man eigentlich ein Array einsetzen will Aber dann bitte so oder ähnlich:
1 | |
2 | |
3 | |
4 | |
5 | |
Inlined ist das auch nicht schlechter.
Klaus schrieb: > Nimm an, C1CTRL sei als char * deklariert. Hast du schon mal ein µC-Register gesehen, das als Pointer deklariert wurde? > Dann wäre die Funktion: > funktion (registertyp x) { > x = 7; > } Also so? funktion (char *x) { x = 7; } Das wär erstens ein Fehler und zweitens einfach nur nix.
Clemens L. schrieb: > Üblicherweise sind solche Registersymbole als "volatile" definiert, und > benutzen irgendeine Compiler-spezifische Magie, um sie an eine feste > Adresse zu legen Nein, keine Magie sondern ganz normales C.