mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik #define soll gleichzeitig Setzen und Löschen


Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

Frage vorweg: wie heisst das, was man durch ein #define definiert?

Frage hinterher: ich habe am Atmega einen Demux angeschlossen, der 3 
Adress-Eingänge besitzt, welche an den Atmega-Ports hängen.

A0  A1  A2  Y
0   0   0   0
1   0   0   1
0   1   0   2
1   1   0   3
0   0   1   4

Nun möchte ich gern durch ein einfaches

#define dmux_input_(0-4)

machen, dass die entsprechende Bitmaske gesetzt wird. Ich kenne aber nur 
Maskierungen, bei denen gleichzeitig ein oder mehrere Bits gesetzt (bzw. 
gelöscht) werden, nicht aber gesetzt UND gelöscht.
Wie tut Mann das?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> ... bei denen gleichzeitig ein oder mehrere Bits gesetzt (bzw. gelöscht) ...

Dann mach das doch:

#define SET_MUX(x) do { PORTX=(PORTX & ~0x07)|(x) } while (0)

und falls es ohne klammer gehen soll:

#define SET_MUX_1 SET_MUX(1)

Stephan R. schrieb:
> Frage vorweg: wie heisst das, was man durch ein #define definiert?

"Makro". ist eine reine Text-Ersetzung, die noch VOR dem Kompilieren 
ausgeführt wird.

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dacht ich auch zuerst, aber der restliche Port wird auch verwendet, es 
dürfen also nur PORTC0 bis PORTC3 verändert werden.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Dacht ich auch zuerst, aber der restliche Port wird auch verwendet, es
> dürfen also nur PORTC0 bis PORTC3 verändert werden.

Genau das macht das Makro doch.
Zuerst wird 0x07 invertiert, ergibt eine Bitmaske 0b11111000.

der PORTC-Zustand wird damit ver-UND-et, d.H. alle bits bis auf die 
untersten drei bleiben wie sie sind.

Danach wird der Makro-Parameter dazu ver-ODER-t, es werden also 
zusätzlich wieder bits gesetzt.

Solange X keine bits anfasst, die es nicht darf, bleibt der Rest von 
PORTC also unverändert.

Wenn du dir selbst nicht traust, kann das Makro das auch erzwingen:
#define SET_MUX(x) do { PORTX=(PORTX & ~0x07)|((x) & 0x07); } while (0)

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist grad mal harter Tobak für mich! Ich hatte mich (gerade aus dem 
Bascom-Lager kommend) schön an die

PORTC |= (1 << PC2)

Schreibweise gewöhnt.

Ich verstehe die Funktion der (x)- Klammer nicht. Steht die nur zur 
Anschauung da oder kann ich die ins Programm übernehmen?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Ich verstehe die Funktion der (x)- Klammer nicht. Steht die nur zur
> Anschauung da oder kann ich die ins Programm übernehmen?

Das ist ein Parameter.
Wenn du im Programm später
SET_MUX(42);
 schreibst, sieht der Compiler:
do { PORTX=(PORTX & ~0x07)|((42) & 0x07); } while (0);
und macht Das Richtige™

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn 
auch einen Prototypen?

Noch was: mein Compiler (Programmers Notepad) formatiert das Makro nicht 
farbig wie in deinem Beispiel sondern nur braun. Warum des?

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anscheinend nicht, zumindest klappts auch so!
Schönen Dank, darfst Dir ein Bier nehmen!

Autor: Jockel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn
> auch einen Prototypen?

Das ist ein Irrtum. Es sieht nur so aus.
Lies nochmal, was Ernst B* oben schrieb (Textersatz).

Jockel

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

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn
> auch einen Prototypen?

Du brauchst ganz, ganz, ganz dringend ein C-Buch.

Das anlassbedingte Zusammentragen von Halbwissen in einem Forum 
funktioniert einfach nicht, wenn man eine Programmiersprache wie C 
lernen will.

Autor: Verwirrter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es einen Grund dafür das Ganze in eine "Schleife" zu packen, warum 
reicht nicht nur die Zuweisung ?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verwirrter schrieb:
> Gibt es einen Grund dafür das Ganze in eine "Schleife" zu packen, warum
> reicht nicht nur die Zuweisung ?

in dem Fall würde es ohne das "while"-Konstrukt auch gehen.

bei "#define ABC(x) a=(x); b=(x)+2" z.B
gäbe es aber ein Problem bei Verwendungen wie:

if (a==23) ABC(42);

(Textersetzung mal von Hand durchführen, wenn das Problem nicht 
offensichtlich ist)

durch das "do-while"-Konstrukt wird das umgangen.


Preprozessor-Makros sind da immer etwas eigen. Anfängern würde ich 
vorschlagen davon ganz die Finger zu lassen, und normale C-Funktionen zu 
verwenden. Wenn man die "Verstanden" hat, kann man sich immer noch 
Makros zur "Optimierung" erlernen.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Noch was: mein Compiler (Programmers Notepad) formatiert das Makro nicht
> farbig wie in deinem Beispiel sondern nur braun. Warum des?
Das nennt sich Syntax-Highlighting und die Farben sind in jedem Editor 
entweder anders oder einstellbar...

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Das anlassbedingte Zusammentragen von Halbwissen

Oder auch learning by doing find ich eigentlich ganz praktisch. Was ich 
nicht brauch, verlern ich gern schnell wieder.


Karl heinz Buchegger schrieb:
> Du brauchst ganz, ganz, ganz dringend ein C-Buch.

Da hinten in der Schublade liegt´s! DUCK UND WEG

Autor: (Ex-)Verwirrter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke mit so etwas hatte ich gerechnet,
bei manchen Compilern kann man das auch einfach in geschweifte Klammern
{ .... } packen. Solche kleineren Blöcke stören dann nicht weiter. 
Zumindest solange man keine, dadurch lokalen, Variablen anlegt.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Ex-)Verwirrter schrieb:
> Danke mit so etwas hatte ich gerechnet,
> bei manchen Compilern kann man das auch einfach in geschweifte Klammern
> { .... } packen. Solche kleineren Blöcke stören dann nicht weiter.
> Zumindest solange man keine, dadurch lokalen, Variablen anlegt.

Nicht immer: ;)
#define TEST(X) do { printf("%d\n",(X)); } while(0)

 if (x)
    TEST(x);
  else
    TEST(x+x);

funktioniert,
#define TEST(X)  { printf("%d\n",(X)); }

 if (x)
    TEST(x);
  else
    TEST(x+x);

Gibt nen Compiler-Fehler:
> »else« ohne vorheriges »if«

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

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Karl heinz Buchegger schrieb:
>> Das anlassbedingte Zusammentragen von Halbwissen
>
> Oder auch learning by doing find ich eigentlich ganz praktisch. Was ich
> nicht brauch, verlern ich gern schnell wieder.

Dazu musst du es aber erst einmal gelernt haben.
Und gerade in C gibt es Unmengen an Fallen und 'Insider-Wissen', ohne 
das man nicht weit kommt.

Und mit Verlaub: So toll ist deine C-Performance nicht. Sie zeigt 
eigentlich genau das Übliche, was man von einem Foren-Zusammenklauber 
erwarten würde: Er kann von allem ein bischen was, aber nichts richtig 
und manchmal einfach nur grundfalsch. Und da red ich noch nicht einmal 
von den wirklich komplizierten Dingen.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also in meinem Buch steht, man solle es mit runden Klammern versuchen.

#define QUADRAT(x) ((x)*(x))

Autor: Stephan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das stimmt natürlich- wenn man denn den Anspruch hat, C professionell zu 
beherrschen.
Das Gute für mich daran: ich brauch mir nicht meine Brötchen damit 
verdienen sondern will nur ein kleines Uböötchen damit auslaufen lassen.
Aber in der Aussicht, vielleicht mal in die Programmiererriege "meiner" 
Firma aufzurutschen, beleg ich nu ein, zwei Semsester lang 
"Programmieren". Vielleicht kann ich ja noch was lernen...

Autor: schau genau (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ernst:
> Wenn du im Programm später

>   SET_MUX(42);

> schreibst, sieht der Compiler:

>   do { PORTX=(PORTX & ~0x07)|((42) & 0x07); } while (0);

> und macht Das Richtige™


Nö, stimmt nicht ganz. er sieht um die 42 keine Klammern, die müsstest 
(und sollst) Du im Define angeben.


Probier mal aus:
#define QUAD1(x) (x*x)
#define QUAD2(x) ((x)*(x))

das ist zwar auf den ersten Blick das selbe, aber beim Aufruf von z.B.
  QUAD(6 & 6);
kommt für QUAD1 4 heraus und für QUAD2 36, denn der Compiler sieht bei
  QUAD1 (6 & 6 * 6 & 6)
eben keine Klammern und rechnet 6 & (6*6) & 6 , weil & eine kleinere 
Hierarchiestufe als * hat.

Typische C-Falle, auf die in jedem guten C-Buch hingewiesen wird.

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

Bewertung
0 lesenswert
nicht lesenswert
schau genau schrieb:

> Probier mal aus:
> #define QUAD1(x) (x*x)
> #define QUAD2(x) ((x)*(x))
>
> das ist zwar auf den ersten Blick das selbe, aber beim Aufruf von z.B.
>   QUAD(6 & 6);

....

Genauso bei

   QUAD( 6 + 1 );

(da ist es vielleicht offensichtlicher und im Kopf leichter zu verfolgen 
als mit einem binären und)

Beliebt sind auch

   i = 7;
   j = QUAD( i++ )

(welchen Wert hat i nach der Operation und was ist das Ergebnis? Ist die 
Operation überhaupt definiert? Wenn ja: warum? Wenn nein: warum nicht?)

> Typische C-Falle, auf die in jedem guten C-Buch hingewiesen wird.
Ganz genau
Dazu muss man aber erst einmal verinnerlicht haben, dass Makros einfach 
nur Textersetzung machen und nicht mehr. Aber auch das steht im besagten 
Buch. Zusammen mit ein paar Beispielen, die zeigen wie sich das auswirkt 
und was da im Präprozessor wirklich passiert.

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

Bewertung
0 lesenswert
nicht lesenswert
Stephan R. schrieb:
> Das stimmt natürlich- wenn man denn den Anspruch hat, C professionell zu
> beherrschen.

Eben nicht
Ohne einen gewissen Grundstock kannst du auch als Amateur nicht sinnvoll 
programmieren.

Von dem was dir jetzt kompliziert vorkommt, bis zu dem, was von einem 
Profi selbstverständlich erwartet und verlangt wird, ist noch ein 
weiter, weiter Weg. Da passt noch viel dazwischen.


Egal ob du Amateur oder Profi- Radrennfahrer bist, Gleichgewicht halten 
müssen beide können. Und man kann sich bei einem Sturz nicht darauf 
rausreden, dass man eben kein Profi sei.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schau genau schrieb:
> Ernst:
>> Wenn du im Programm später
>
>>   SET_MUX(42);
>
>> schreibst, sieht der Compiler:
>
>>   do { PORTX=(PORTX & ~0x07)|((42) & 0x07); } while (0);
>
>> und macht Das Richtige™
>
>
> Nö, stimmt nicht ganz. er sieht um die 42 keine Klammern, die müsstest
> (und sollst) Du im Define angeben.

in dem Satz fehlt das "und hast" ...
mein #define hat die extra-Klammerung um das "x", also selber "genau 
schau"en ;)

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.