mikrocontroller.net

Forum: Compiler & IDEs Frage Makro-Frage


Autor: Ulrich Schneider (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe leider noch wenig Erfahrung mit C und GCC und eine kleine
"Ist das irgendwie möglich"-Frage zu Makros.

Folgendes Problem:
Ich habe angefangen für die Atmel AVRs zu programmieren, würde aber
gerne den Sourcecode etwas einfacher, lesbarer und weniger auf eine
spezielle Architektur zugeschnitten haben, was die einfache Ein/Ausgabe
auf bestimmte IO-Ports betrifft. Genauer gesagt möchte ich zum
Ein-/Aus-/Umschalten/Richtung bestimmen für ein bestimmtes Port-Pin im
Quelltext nur eine einzige Variable benutzen.

Mal ein Beispiel: Ich würde ich beispielsweise gerne so etwas wie

SET_IO_PORT_TO_OUTPUT( PORT_C5 )
schreiben statt
DDRC |= (1 << DDC5)

oder

SET_OUTPUT_PORT_LOW( PORT_D2 )
statt
PORTD &= ~(1 << PD2)

Allerdings hätte ich es gerne so, dass der kompilierte Code dadurch
nicht grösser und langsamer wird; wenn es also beispielsweise möglich
wäre dass der GCC-Preprozessor den Makroaufruf
SET_IO_PORT_TO_OUTPUT( PORT_C5 )
automatisch in ein
DDRC |= (1 << DDC5)
umformt.

Ist das irgendwie möglich? Das Problem das ich habe ist, dass er zu
jeder Angabe wie PORT_C5 automatisch die passenden Werte der anderen
DDR, PORT und PIN-Register wissen muss (bei PORT_C5 also z.B. DDRC,
PORTC, PINC)

Da DDRC, PINC etc. ja vermutlich letztlich nur Werte sind dachte ich
ich löse das einfach, indem ich die entsprechenden Werte in eine
grössere Zahl "hineinpacke" und sie daraus dann wieder extrahiere,
z.B.

#define PORT_C5  ((DDRC << 24) | (PINC << 16) | (PORTC << 8) | 5)
[...]
#define DDR(port) (uint8_t)(port >> 24)
#define BITINDEX(port) (uint8_t)(port)
#define SET_IO_PORT_TO_OUTPUT(port) DDR(port) |= (1 << BITINDEX(port))

War auch schön gedacht, funktioniert aber leider nicht - aufgrund der
Fehlermeldung "invalid lvalue in assignment" gehe ich davon aus dass
das Problem ist, dass nach allen Ersetzungen durch den Preprozessor ein
Aufruf wie
SET_IO_PORT_TO_OUTPUT( PORT_C5 )
nicht durch
DDRC |= (1 << 5)
ersetzt wird sondern durch sowas wie
12 |= (1 << 5)

Hat Jemand eine Idee, wie ich das Problem trotzdem lösen könnte?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, wenn du sowas akzeptierst:
#define SET_IO_PORT_TO_OUTPUT(port,pin) DDR##port |= (1 << (pin))
...
SET_IO_PORT_TO_OUTPUT(C,5);

dann geht es.

Das nennt man auch einen hardware abstraction layer (HAL).

Autor: Ulrich Schneider (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Tip, Jörn, auf die Idee bin ich nicht gekommen. Allerdings
hätte ich dann ja trotzdem noch zwei Parameter in jedem Aufruf, und wenn
es irgendwie mit einem ginge, das wäre halt noch schöner...

Das praktische wenn ich nur einen Parameter hätte wäre halt auch, dass
ich dann auch sowas schreiben könnte wie

#define POWER_STATUS_LED_IO_PORT PORT_C5
[...]
SET_IO_PORT_TO_OUTPUT( POWER_STATUS_LED_IO_PORT );

und falls ich mich dann entscheiden sollte die Power-LED an einen
anderen IO-Pin zu klemmen, dann müsste ich nur einen einzigen Wert
ändern.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define SET_IO_PORT_TO_OUTPUT_internal(port,pin) DDR##port |= (1 <<
(pin))
#define SET_IO_PORT_TO_OUTPUT(y) SET_IO_PORT_TO_OUTPUT_internal(y)
#define POWER_STATUS_LED_IO_PORT C,5

SET_IO_PORT_TO_OUTPUT(POWER_STATUS_LED_IO_PORT);

Autor: Ulrich Schneider (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert einwandfrei - vielen Dank!!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.