mikrocontroller.net

Forum: PC-Programmierung Makro im Makro C


Autor: Dennis A. (dennis999)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich würde gerne meinen C-Code etwas kompakter mit Makros darstellen. 
Hatte da zwei verschiedene Ideen um ein Makro zum ändern von PINs zu 
erstellen.
#define TOGGLE(PORT,SDA,SCL) \
  ##PORTSEL &=  ~BIT##SDA; \
  ##PORTSEL &=  ~BIT##SCL; \
  ##PORTOUT &=  ~BIT##SCL; \
  ##PORTOUT &=  ~BIT##SDA; \
  ##PORTDIR |=   BIT##SCL; \
  ##PORTDIR &=  ~BIT##SDA; \
  break;

TOGGLE(P3,4,5)
#define TOGGLE(PORT,SDA,SCL) \
  P##PORTSEL &=  ~BIT##SDA; \
  P##PORTSEL &=  ~BIT##SCL; \
  P##PORTOUT &=  ~BIT##SCL; \
  P##PORTOUT &=  ~BIT##SDA; \
  P##PORTDIR |=   BIT##SCL; \
  P##PORTDIR &=  ~BIT##SDA; \
  break;

TOGGLE(3,4,5)

## am Anfang einer Zeile scheint der Compiler (IAR Workbench; MSP430) 
nicht zu mögen. Und innerhalb mag er es auch nicht - "identifier 
PPORTSEL is undefined"

Vielleicht weiß ja jemand, ob es überhaupt möglich ist in ein Makro in 
ein anderes einzusetzen und wie man das am besten macht.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Haben die beiden Doppelkreuze vor PORTSEL denn einen tieferen Sinn? Was 
ist denn PORTSEL überhaupt?

Autor: Dennis A. (dennis999)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist, dass PXSEL die Funktion des PORTs auswählt (also I/O 
etc), und selbst ein Makro ist. Hinter P3SEL steht z.B. 0x001B. Daneben 
gibt es dann eben noch P2SEL etc.

Und eben dieses Port-Nummer (X) soll durch den Makroparaemter PORT 
ersetzt werden.

Analog ist gilt dass dann auch für PXOUT und PXDIR.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das '##' muss zwischen den Makroargumenten und dem Text stehen, mit dem
sie verbunden werden sollen:
#define P3SEL (*(volatile unsigned char *)0x001B)
#define P3OUT (*(volatile unsigned char *)0x001C)
#define P3DIR (*(volatile unsigned char *)0x001D)

#define TOGGLE1(port,sda,sdl) do {\
  port##SEL &=  ~BIT##sda; \
  port##SEL &=  ~BIT##sdl; \
  port##OUT &=  ~BIT##sda; \
  port##OUT &=  ~BIT##sdl; \
  port##DIR |=   BIT##sda; \
  port##DIR &=  ~BIT##sdl; \
  } while(0)

TOGGLE1(P3,4,5);

#define TOGGLE2(port,sda,sdl) do {\
  P##port##SEL &=  ~BIT##sda; \
  P##port##SEL &=  ~BIT##sdl; \
  P##port##OUT &=  ~BIT##sda; \
  P##port##OUT &=  ~BIT##sdl; \
  P##port##DIR |=   BIT##sda; \
  P##port##DIR &=  ~BIT##sdl; \
  } while(0)

TOGGLE2(3,4,5);

Zum Testen habe ich P3SEL usw. mal irgendwie definiert. Die Definitionen
in den Headerfiles werden natürlich etwas davon abweichen. Der do-while-
Trick dient dazu, aus mehreren Anweisungen eine einzige zu machen, so
dass das Makroaufruf syntaktisch gleich wie eine Funktion verwendet
werden kann (auch in if-Anweisungen u.ä.).

Präprozessorausgabe für beide Makros:
do {
  (*(volatile unsigned char *)0x001B) &= ~BIT4;
  (*(volatile unsigned char *)0x001B) &= ~BIT5;
  (*(volatile unsigned char *)0x001C) &= ~BIT4;
  (*(volatile unsigned char *)0x001C) &= ~BIT5;
  (*(volatile unsigned char *)0x001D) |=  BIT4;
  (*(volatile unsigned char *)0x001D) &= ~BIT5;
} while(0);


Autor: Dennis A. (dennis999)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok hab's herausgefunden:
#define TOGGLE(PORT,SDA,SCL) \
    P##PORT##SEL &=  ~BIT##SDA; \
    P##PORT##SEL &=  ~BIT##SCL; \
    P##PORT##OUT &=  ~BIT##SCL; \
    P##PORT##OUT &=  ~BIT##SDA; \
    P##PORT##DIR |=   BIT##SCL; \
    P##PORT##DIR &=  ~BIT##SDA; \
    break;

TOGGLE(2,3,4)
TOGGLE(1,2,3)
...

Falls nach dem Makroparameter noch was kommt, muss man ## nach dem 
Makroparameter setzen.

Autor: Dennis A. (dennis999)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke  Yalu. Hab deine Antwort leider erst nach meinem Post gelesen.

Vielleicht weiß noch jemand wie ich ein Makro in " " einbinden kann.

z.B. bei folgendem Code:
#define TEST(ID) \
   uartSendstr("Mein Parameter ist ID");

TEST(1)
TEST(2)
...

Dabei will die Funktion uartSendstr( *char ) übergeben haben.

Habe es mit ID, ##ID, ##ID## ausprobiert. Aber die Ausgabe ist immer ID, 
##ID oder ##ID## und nicht der gewünschte Makroparameter 1, 2...

Mir ist nicht ganz klar woran das liegt, denn der Präprozessor sollte 
doch ID einfach stur ersetzen können? Oder übergeht der das wegen den 
Anführungszeichen?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dennis A. schrieb:
#define TEST(ID) \
   uartSendstr("Mein Parameter ist " #ID);

TEST(1)
TEST(2)
...


> Mir ist nicht ganz klar woran das liegt, denn der Präprozessor sollte
> doch ID einfach stur ersetzen können? Oder übergeht der das wegen den
> Anführungszeichen?
Ne, Token-Paste (##) funktioniert meistens immer nur bei Bezeichnern. 
Der Präpro zieht aber hintereinanderstehende Strings zu einem zusammen, 
daher kann man die ID mit dem Stringify-Operator (#) zum String machen.

Autor: Dennis A. (dennis999)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super funktioniert. 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.