Makro im Makro C

#1587334
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.
1
#define TOGGLE(PORT,SDA,SCL) \
2
  ##PORTSEL &=  ~BIT##SDA; \
3
  ##PORTSEL &=  ~BIT##SCL; \
4
  ##PORTOUT &=  ~BIT##SCL; \
5
  ##PORTOUT &=  ~BIT##SDA; \
6
  ##PORTDIR |=   BIT##SCL; \
7
  ##PORTDIR &=  ~BIT##SDA; \
8
  break;
9

10
TOGGLE(P3,4,5)
1
#define TOGGLE(PORT,SDA,SCL) \
2
  P##PORTSEL &=  ~BIT##SDA; \
3
  P##PORTSEL &=  ~BIT##SCL; \
4
  P##PORTOUT &=  ~BIT##SCL; \
5
  P##PORTOUT &=  ~BIT##SDA; \
6
  P##PORTDIR |=   BIT##SCL; \
7
  P##PORTDIR &=  ~BIT##SDA; \
8
  break;
9

10
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.
#1587359
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.
Moderator #1587436
Lesenswert?

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

5
#define TOGGLE1(port,sda,sdl) do {\
6
  port##SEL &=  ~BIT##sda; \
7
  port##SEL &=  ~BIT##sdl; \
8
  port##OUT &=  ~BIT##sda; \
9
  port##OUT &=  ~BIT##sdl; \
10
  port##DIR |=   BIT##sda; \
11
  port##DIR &=  ~BIT##sdl; \
12
  } while(0)
13

14
TOGGLE1(P3,4,5);
15

16
#define TOGGLE2(port,sda,sdl) do {\
17
  P##port##SEL &=  ~BIT##sda; \
18
  P##port##SEL &=  ~BIT##sdl; \
19
  P##port##OUT &=  ~BIT##sda; \
20
  P##port##OUT &=  ~BIT##sdl; \
21
  P##port##DIR |=   BIT##sda; \
22
  P##port##DIR &=  ~BIT##sdl; \
23
  } while(0)
24

25
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:
1
do {
2
  (*(volatile unsigned char *)0x001B) &= ~BIT4;
3
  (*(volatile unsigned char *)0x001B) &= ~BIT5;
4
  (*(volatile unsigned char *)0x001C) &= ~BIT4;
5
  (*(volatile unsigned char *)0x001C) &= ~BIT5;
6
  (*(volatile unsigned char *)0x001D) |=  BIT4;
7
  (*(volatile unsigned char *)0x001D) &= ~BIT5;
8
} while(0);
#1587437
Lesenswert?

Ok hab's herausgefunden:
1
#define TOGGLE(PORT,SDA,SCL) \
2
    P##PORT##SEL &=  ~BIT##SDA; \
3
    P##PORT##SEL &=  ~BIT##SCL; \
4
    P##PORT##OUT &=  ~BIT##SCL; \
5
    P##PORT##OUT &=  ~BIT##SDA; \
6
    P##PORT##DIR |=   BIT##SCL; \
7
    P##PORT##DIR &=  ~BIT##SDA; \
8
    break;
9

10
TOGGLE(2,3,4)
11
TOGGLE(1,2,3)
12
...

Falls nach dem Makroparameter noch was kommt, muss man ## nach dem 
Makroparameter setzen.
#1587533
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:
1
#define TEST(ID) \
2
   uartSendstr("Mein Parameter ist ID");
3

4
TEST(1)
5
TEST(2)
6
...

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?
Gast #1587535
Lesenswert?

Dennis A. schrieb:
1
#define TEST(ID) \
2
   uartSendstr("Mein Parameter ist " #ID);
3

4
TEST(1)
5
TEST(2)
6
...


> 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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren