www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit if-Abfrage


Autor: Günther (Gast)
Datum:

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

Autor: ---- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (PINB & 16)
 anweisung1;
else
 anweisung2;

Autor: ---- (Gast)
Datum:

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

Autor: Günther (Gast)
Datum:

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

Autor: Günther (Gast)
Datum:

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

Autor: ---- (Gast)
Datum:

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

Autor: ---- (Gast)
Datum:

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

Autor: ---- (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Christian Schifferle (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Günther (Gast)
Datum:

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

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.