www.mikrocontroller.net

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


Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Tropenhitze (Gast)
Datum:

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

Autor: Tropenhitze (Gast)
Datum:

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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald schrieb:

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

Funktionen sind zwar übersichtlicher, aber wenn schon, dann:
#define GRUEN_1() do{ P2OUT &= ~(ROT1 + ROT2); \
                      P1OUT &= ~GRUEN2; \
                      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.

Autor: Stefan (Gast)
Datum:

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

Autor: Harald (Gast)
Datum:

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

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: A. K. (prx)
Datum:

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

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar, besten Dank!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktionen sind trotzdem besser!
Vor allem für einen Neuling!

Autor: Tropenhitze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Thorsten M... (thorstenm)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Tropenhitze (Gast)
Datum:

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

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define   GREEN_H             (P1OUT  |=  (0x01))
#define   GREEN_L             (P1OUT  &= ~(0x01))
#define   RED_H               (P1OUT  |=  (0x04))
#define   RED_L               (P1OUT  &= ~(0x04))

#define SET_GREEN    {GREEN_H; RED_L;}
#define SET_RED      {RED_H; GREEN_L;}

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.