Forum: Compiler & IDEs Anfängerfrage zu Vergleichsoperation


von Achim (Gast)


Lesenswert?

Hi, vielleicht kann mir ja jemand auf die Sprünge helfen.
Betrifft ATTINY44 und WinAVR.
Ich versteh nicht wie ich einen Vergleich anstellen muss:
Der Disassembler übersetzt:
1
375:        if (ADMUX==ADMUX_THR)  
2
+000001E2:   B187        IN        R24,0x07       In from I/O location
Das funktioniert nicht so, wie ich will. Hingegen funktionert richtig:
1
375:        if (ADMUX==131)  
2
+000001E2:   B187        IN        R24,0x07       In from I/O location
3
+000001E3:   3883        CPI       R24,0x83       Compare with immediate
4
+000001E4:   F009        BREQ      PC+0x02        Branch if equal
5
+000001E5:   C057        RJMP      PC+0x0058      Relative jump
Eigentlich will ich die Einstellung in ADMUX prüfen.
Vorher habe ich definiert:
1
#define THR_INPUT_PIN    PINA3
2
#define ADMUX_THR  (uint8_t)  (1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN
3
4
ADMUX=ADMUX_THR;
Warum läd WinAVR bei "if (ADMUX==ADMUX_THR)" einfach nur ADMUX in R24 
und weiter nichts?
Was mache ich falsch?

von Mark B. (markbrandis)


Lesenswert?

Klammerung beim Makro vielleicht?
1
#define ADMUX_THR ( (uint8_t)  ((1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN) )

von tuppes (Gast)


Lesenswert?

Offenbar glaubt der Compiler, dass das Vergleichsergebnis (ADMUX == 
ADMUX_THR) von nichts abhängt, also immer false oder immer true ist. Ich 
tippe auf einen Fehler in den Makros.

Wie ist PINA3 definiert?

Hinweis: Der Cast auf (uint8_t) wirkt nur auf den vordersten 
Klammerausdruck (1 << REFS1). Der Gesamtausdruck erfährt danach noch 
eine Integer-Promotion, so weit wie nötig, um die auftretenden Werte 
darzustellen (ggfs. bis unsigned long).

von Oliver (Gast)


Lesenswert?

>main.c:12: warning: suggest parentheses around comparison in operand of |

Klammern sind in C nie zuviel, immer nur zuwenig.

== hat eine höhere Precedence als | , und damit macht die Zeile
1
if (ADMUX== (uint8_t)  (1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN))

etwas ganz anderes, als du eigentlich beabsichtigst. Der Klammerausdruck 
ist immer wahr (warum das so ist, kannst du ja selber mal rausknobeln), 
und dann schlägt der Optimierer zu, und optimiert den Vergleich weg. 
ADMUX wird aber trotzdem gelesen, da volatile.

Mit
1
#define ADMUX_THR  ((uint8_t)  ((1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN))

funktioniert dein Programm so, wie du erwartest.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Achim schrieb:

> Was mache ich falsch?

Spiel doch einfach mal Präprozessor und mach die Textersetzung genau so, 
wie sie auch der Präprozessor vornimmt.

Du hast

   if (ADMUX==ADMUX_THR)

und jetzt ersetzt du den Text ADMUX_THR durch

(uint8_t)  (1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN

Dann kriegst du

   if( ADMUX==(uint8_t)  (1<<REFS1) | (0<<REFS0)|THR_INPUT_PIN )

und jetzt gliederst du das mal nach den C-Regelen

   if( ADMUX == (uint8_t)  (1<<REFS1) |
       (0<<REFS0) |
       THR_INPUT_PIN )

Deine Abfrage besteht also aus 3 Teilausdrücken:
   ob ADMUX gleich 1 << REFS1 ist
   Dem Wert von 0 << REFS0
   und dem Wert von THR_INPUT_PIN

Alle 3 Teilbedingungen werden mit einem binären Oder miteinander 
verknüpft und das Gesamtergebnis entscheidet dann ob der then Zweig 
genommen wird.

von Achim (Gast)


Lesenswert?

Tausend Dank für eure schnelle Hilfe! Es klappt!
Ich habe wirklich auch die Warnung übersehen (schäm...)...

Danke auch Karl heinz für den Tip fürs Weiterstudieren!

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.