Forum: Mikrocontroller und Digitale Elektronik IAR: Ausdrücke in #define-Anweisung zusammenfassen


von Harald (Gast)


Lesenswert?

Hallo liebe Leute

Vorab: Ich benutze einen MSP430.

Ich habe eine Frage, und zwar möchte ich zu Beginn meines Programms 
mehrere #define-Anweisungen festlegen, um mir Schreibarbeit zu sparen.


#define IN     P1IN   // Port 1 Eingang
#define TASTER 0x20   // P1.5
#define GRUEN1 0x01   // P1.0
#define GRUEN2 0x02   // P1.1
#define ROT1   0x40   // P2.6
#define ROT2   0x80   // P2.7

#define GRUEN_1 ((P2OUT &= ~(ROT1 + ROT2)) && (P1OUT &= ~GRUEN2) && 
(P1OUT |= GRUEN1))

#define ROT_1   ((P1OUT &= ~(GRUEN1 + GRUEN2)) && (P2OUT &= ~ROT2) && 
(P2OUT |= ROT2))

#define GRUEN_2 ((P2OUT &= ~(ROT1 + ROT2)) && (P1OUT &= ~GRUEN1) && 
(P1OUT |= GRUEN2))

#define ROT_2   ((P1OUT &= ~(GRUEN1 + GRUEN2)) && (P2OUT &= ~ROT1) && 
(P2OUT |= ROT1))

Wenn ich jetzt irgendwo im Text "GRUEN_1" eingebe, dann soll nur die 
eine LED an P1.0 leuchten und die anderen an P1.2, P2.6 und P2.7 eben 
nicht.

Mein Problem liegt in der Verknüpfung der einzelnen Ausdrücke. Gebe ich, 
wie hier jetzt das "&&" ein, so funktioniert es garnicht. Wenn ich die 
"&&"s durch "&" oder durch "+" ersetze, dann funktioniert es, aber es 
kommen Warnungen mit 'undefined behaviour...'.

Wie ist die syntaktische Verknüpfung der einzelnen Ausdrücke? KAnn mir 
da jemand helfen?


Danke schonmal!

von Tropenhitze (Gast)


Lesenswert?

> um mir Schreibarbeit zu sparen.

Dann schreibe Dir am besten kleine Funktionen, die Jeder und vor allem 
auch Du selbst verstehen kann. Dann kannst Du auch ausschließen, dass 
die anderen Pins der Ports 1+2 korrekt behandelt werden.

von Tropenhitze (Gast)


Lesenswert?

Korrektur:
... ausschließen, dass sie nicht korrekt behandelt werden.
Die anderen Pins sollten ja unverändert in ihrem Zustand und ihrer 
Funktion bleiben.

von (prx) A. K. (prx)


Lesenswert?

Harald schrieb:

> #define GRUEN_1 ((P2OUT &= ~(ROT1 + ROT2)) && (P1OUT &= ~GRUEN2) &&
> (P1OUT |= GRUEN1))

Funktionen sind zwar übersichtlicher, aber wenn schon, dann:
1
#define GRUEN_1() do{ P2OUT &= ~(ROT1 + ROT2); \
2
                      P1OUT &= ~GRUEN2; \
3
                      P1OUT |= GRUEN1; }while(0)

Diese sinnlos wirkende do{...}while(0) Konstruktion statt einfachem 
{...} vermeidet Probleme, die sonst bei funktionsartiger Verwendung mit 
einem abschliessenden ; entstehen können, denn bei
  if (...) GRUEN_1(); else ...
liefert
  if (...) {...}; else ...
einen Syntaxfehler,
  if (...) do{...}while(0); else ...
jedoch nicht.

von Stefan (Gast)


Lesenswert?

Ich verwende gerne Ausdrücke in der Form:
1
#define   SET_GREEN               (P1OUT  |=  (0x01))     // P1.0  high
2
#define   RESET_GREEN             (P1OUT  &= ~(0x01))     // P1.0  low

von Harald (Gast)


Lesenswert?

Ja, das habe ich bis jetzt auch gemacht, jedoch muss ich dann an jeder 
Stelle die entsprechenden LEDs einzeln an und ausschalten. Das ist halt 
jedesmal mehr Text. Ein #define wäre da handlicher.

von Harald (Gast)


Lesenswert?

A. K. schrieb:
> Funktionen sind zwar übersichtlicher, aber wenn schon, dann:
> #define GRUEN_1() do{ P2OUT &= ~(ROT1 + ROT2); \
>                       P1OUT &= ~GRUEN2; \
>                       P1OUT |= GRUEN1; }while(0)

Hey, super, das funktioniert gut! Danke, Kannst du mir noch verraten, 
was das "\" zwischen den einzelnen Anweisungen bewirkt?

Danke!

von (prx) A. K. (prx)


Lesenswert?

Harald schrieb:

> Hey, super, das funktioniert gut! Danke, Kannst du mir noch verraten,
> was das "\" zwischen den einzelnen Anweisungen bewirkt?

Präprozessoranweisungen sind normalerweise nur eine Zeile lang. So 
lassen sie sich verlängern.

von Harald (Gast)


Lesenswert?

Alles klar, besten Dank!

von Karl H. (kbuchegg)


Lesenswert?

Funktionen sind trotzdem besser!
Vor allem für einen Neuling!

von Tropenhitze (Gast)


Lesenswert?

Mich würde auch interessieren, welcher Code für jeden 'Aufruf' erzeugt 
wird.
Kannst Du mal den passenden Ausschnitt aus der *.lst Datei zeigen?

von Thorsten M. (thorstenm)


Lesenswert?

Man könnte auch den Teil der Sprache nutzen, der dafür gedacht ist, 
logische und syntaktische Verknüpfungen auszudrücken und Schreibarbeit 
zu sparen, nämlich C-Funktionen statt den Präprozessor.

Eine LED-"API" a la set_leds(GREEN1_ONLY, ON) ist für jeden 
verständlich, sie funktioniert immer fehlerfrei ohne while(0)-Gebastel 
und ist effizient genug für Geblinke und Tastendrücke (und alles andere 
wahrscheinlich auch).

EDIT: Karl heinz war schneller.

von Karl H. (kbuchegg)


Lesenswert?

Thorsten M... schrieb:
> Man könnte auch den Teil der Sprache nutzen, der dafür gedacht ist,
> logische und syntaktische Verknüpfungen auszudrücken und Schreibarbeit
> zu sparen, nämlich C-Funktionen statt den Präprozessor.
>
> Eine LED-"API" a la set_leds(GREEN1_ONLY, ON) ist für jeden
> verständlich, sie funktioniert immer fehlerfrei ohne while(0)-Gebastel
> und ist effizient genug für Geblinke und Tastendrücke (und alles andere
> wahrscheinlich auch).

Ich finde:
Für eine einzelne LED ist ein Makro noch ok (obwohl man auch da 
debattieren kann).
Aber spätestens dann, wenn mehrere Statements in einem Makro verpackt 
werden sollen, fährt man mit einer Funktion immer besser.

Diese Makro Lösungen, mit dem do ... while( 0 ) Hack stammen im Grunde 
alle noch aus einer Zeit, als inlinen mit einem Compiler Glückssache 
war. Und ja, solche Makro-Lösungen fallen einem des öfteren schon auch 
mal nach längerer Zeit auf den Schädel. Denn irgendwelche Nebenwirkungen 
gibt es meistens.

von Tropenhitze (Gast)


Lesenswert?

>Und ja, solche Makro-Lösungen fallen einem des öfteren schon auch
>mal nach längerer Zeit auf den Schädel.

Wie wahr, wie wahr!
Auch ich bin schreibfaul, aber wichtiger ist es, dass man ein Programm 
schnell lesen und begreifen kann. Meister des Faches schreiben ein 
Programm in eine einzige Zeile. Nur wozu soll das gut sein?

Was A.K. vorgeschlagen hat, ist ja letzlich der Rumpf einer Funktion. 
Moderne Compiler optimieren derart, dass sie kleine oder einmalige 
Funktionen inline einfügen, ohne das man irgendwie tricksen müßte.

von Jörg S. (joerg-s)


Lesenswert?

Harald schrieb:
>#define   SET_GREEN               (P1OUT  |=  (0x01))     // P1.0  high
>#define   RESET_GREEN             (P1OUT  &= ~(0x01))     // P1.0  low
> Ja, das habe ich bis jetzt auch gemacht, jedoch muss ich dann an jeder
> Stelle die entsprechenden LEDs einzeln an und ausschalten. Das ist halt
> jedesmal mehr Text. Ein #define wäre da handlicher.

Ist doch auch kein Problem:
1
#define   GREEN_H             (P1OUT  |=  (0x01))
2
#define   GREEN_L             (P1OUT  &= ~(0x01))
3
#define   RED_H               (P1OUT  |=  (0x04))
4
#define   RED_L               (P1OUT  &= ~(0x04))
5
6
#define SET_GREEN    {GREEN_H; RED_L;}
7
#define SET_RED      {RED_H; GREEN_L;}

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.