#define soll gleichzeitig Setzen und Löschen

Gast #1877061
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?
#1877065
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.
#1877083
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:
1
#define SET_MUX(x) do { PORTX=(PORTX & ~0x07)|((x) & 0x07); } while (0)
Gast #1877117
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?
Gast #1877144
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?
#1877233
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.
Gast #1877254
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.
#1877267
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: ;)
1
#define TEST(X) do { printf("%d\n",(X)); } while(0)
2

3
 if (x)
4
    TEST(x);
5
  else
6
    TEST(x+x);

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

3
 if (x)
4
    TEST(x);
5
  else
6
    TEST(x+x);

Gibt nen Compiler-Fehler:
> »else« ohne vorheriges »if«
#1877269
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.
Gast #1877327
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...
Gast #1877402
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.
#1877416
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.
#1877421
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.
#1877852
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

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