Forum: Compiler & IDEs Problem mit if-Abfrage


von Günther (Gast)


Lesenswert?

Hallo,
kann mir jemand schreiben, was ich bei der
nachfolgenden if-Abfrage falsch mache?
Egal, ob ich in die Bedingung eins oder null
einsetze, immer wird Anweisung2 ausgeführt:

if ((PINB &= 16) ==1)
anweisung1   /* z.B. PORTC = 251;*/           else
anweisung2   /* z.B. PORTC127; */

In seltenen Fällen funktioniert es, aber
für die Abfrage eines PWM-Gerätes ist das
zu wenig.
Ich benutze avr-gcc, einen ATmega16 und der
abzufragende Pin liegt über 10k an high.

Kann es sein, daß solche if-Abfragen generell etwas
hakelig sind? Bei der Ansteuerung eines I2C-Bausteins
erhält man auch gelegentlich eine Errormeldung.

mfg
Günther

von ---- (Gast)


Lesenswert?

if (PINB & 16)
 anweisung1;
else
 anweisung2;

von ---- (Gast)


Lesenswert?

Sei gegrüßt fremder "----".

> if ((PINB &= 16) ==1)
zunächst wird PINB &= 16 ausgeführt und das Ergebnis in PINB abgelegt.
PINB kann bei dieser Anweisung aber nur die Werte 0 oder 16 annehmen,
weshalb dein Vergleich dann später auf 1 fehlschlägt.

Laß zudem noch das '=' wech, denn du willst das PINB-Register nicht
mit dem errechneten Wert beschreiben.

Eine Lösung hat ja "----" schon geschrieben.

> Kann es sein, daß solche if-Abfragen generell etwas hakelig sind?
Nein!

> Bei der Ansteuerung eines I2C-Bausteins erhält man auch gelegentlich
eine Errormeldung.
vermutlich Timingprobleme.

----, (QuadDash).
^^^^^^^^^^^^^^^^^ - nur echt mit dieser Sig :)

von Günther (Gast)


Lesenswert?

@---- Wo ist der Unterschied? Solche Dinger habe ich
  natürlich durchprobiert.

  Die Version habe ich aus dem ATmega-Manual übernommen
  (ist dort bei I2C-Ansteuerung beschrieben).





Hier nochmals der Inhalt der lst-Datei

Quellcode:

     if ((PINB & 1<<3) == 1) /*((PINB & _BV(3)) == 1)   (PINB &~8)  */
     PORTC=127;
    else
     PORTC &=251 ;
      PORTC=255;

lst-file
  {
     if ((PINB & 1<<3) == 1) /*((PINB & _BV(3)) == 1)   (PINB &~8)  */
 3a2:  86 b3         in  r24, 0x16  ; 22
 3a4:  99 27         eor  r25, r25
 3a6:  88 70         andi  r24, 0x08  ; 8
 3a8:  90 70         andi  r25, 0x00  ; 0
 3aa:  01 97         sbiw  r24, 0x01  ; 1
 3ac:  19 f0         breq  .+6        ; 0x3b4
     PORTC=127;
    else
     PORTC &=251 ;
 3ae:  aa 98         cbi  0x15, 2  ; 21
      PORTC=255;
 3b0:  25 bb         out  0x15, r18  ; 21
 3b2:  f7 cf         rjmp  .-18       ; 0x3a2
 3b4:  35 bb         out  0x15, r19  ; 21
 3b6:  fc cf         rjmp  .-8        ; 0x3b0

Sieht doch normal aus? Funktioniert trotzdem nicht.

Gruß
Günther

von Günther (Gast)


Lesenswert?

Hi ----, (QuadDash).
    ^^^^^^^^^^^^^^^^^     ( richtig so?)

> if ((PINB &= 16) ==1)
>zunächst wird PINB &= 16 ausgeführt und das Ergebnis in PINB
abgelegt.
>PINB kann bei dieser Anweisung aber nur die Werte 0 oder 16 annehmen,
>weshalb dein Vergleich dann später auf 1 fehlschlägt.

Vielleicht liegt darin mein Denkfehler. Ich will ja nicht wissen,
wie die PINB heißen (also PinB4 =16) sondern was daran anliegt,
also liegt an PIN 4 Null oder Eins an. Danach wollte ich
mit dem if fragen.
Aber wie macht man es richtig?


Gruß
Günther Y

von ---- (Gast)


Lesenswert?

> Sieht doch normal aus? Funktioniert trotzdem nicht.
Selbstzitat: "PINB kann bei dieser Anweisung aber nur die Werte 0 oder
16 annehmen, weshalb dein Vergleich dann später auf 1 fehlschlägt"

Nebenbei zur Info: (PINB & 1<<3) ist ungleich (PINB & 16)

> Die Version habe ich aus dem ATmega-Manual übernommen (ist dort bei
I2C-Ansteuerung beschrieben).
Vermutlich aber nur für den niederwertigsten Pin (PinB0), dann
funktioniert der Vergleich auf 1 nämlich. Ansonsten ist das einfach
falsch.

Und wie du deinem Listfile entnehmen kannst, ist dein Compiler auch
meiner Meinung :)  (PORTC=127; wird wegoptimiert oder interpretier ich
das was falsch?).

----, (QuadDash).

von ---- (Gast)


Lesenswert?

> Hi ----, (QuadDash).
>    ^^^^^^^^^^^^^^^^^     ( richtig so?)
Super ;)  (blöder Name, ich weiss).

> Ich will ja nicht wissen, wie die PINB heißen (also PinB4 =16)
Das hat damit nix zu tun.

> Aber wie macht man es richtig?
Variante 1:  if (PINB & 1<<3)
Variante 2:  if ((PINB & 1<<3) == 0x08)
ist Geschmackssache.

----, (QuadDash).

von ---- (Gast)


Lesenswert?

Variante 3: if ((PINB & 1<<3) == 1<<3)
macht mehr Sinn als Variante 2 - da man sich ja extra für diese
Notation entschieden hat.
Variante 4: if (PINB & 0x08)
Variante 5: if ((PINB & 0x08) == 0x08)

----, (QuadDash).

von Peter D. (peda)


Lesenswert?

if ((PINB & 1<<3) != 0)

klappt mit jeder Bitmaske

Die meisten C-Programmierer wissen aber, daß alles != 0 wahr ist und
schreiben:

if (PINB & 1<<3)



Peter

von Christian Schifferle (Gast)


Lesenswert?

und wenn du noch ein Klammerpaar mehr schreibst ist es sogar auch noch
lesbar:-)

if (PINB & (1<<3))

Gruss
Christian

P.S. Gewisse C-Compiler hatten nämlich ohnehin Problemen mit der
Operator-Reihenfolge der Schiebeoperatoren und hätten den Ausdruck ohne
Klammern falsch ausgewertet.

von Jörg Wunsch (Gast)


Lesenswert?

Die wären allerdings hochgradig kaputt.

Anyway, viele C-Compiler werden das warnen, da man sich als Leser oft
genug nicht sofort im Klaren sein muß, welche der Operatoren den
Vorrang haben.

von Günther (Gast)


Lesenswert?

Hallo,
vielen Dank für die Hinweise,
meine letzten Versuche mit
if (PINB & 8) bzw.
if (PINB & (1<<3)) oder
if (PINB & (_BV(3)))
waren erfolgreich!

Aber jetzt geht es nicht mehr,
weil ich mit TwinAVR keine Verbindung
mehr bekomme. Wer weiß, woran das wieder liegt.
Viele Grüße
Günther

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.