Shift-Problem?

Gast #898877
Hallo zusammen,

ich bin blutiger Anfänger, also bitte um Nachsicht ;-)

In einem Programm möchte ich warten, bis auf PIND die letzten drei Bits 
1 sind. Meine Frage:

Warum tut es so:
1
while(~PIND & 0b00000111){warte();}

aber nicht so:
1
while((PIND << 5) != 0b11100000){warte();}

Die obere Bedingung wird false, wenn alle drei Bits 1 sind, wie 
gewünscht. Die untere Bedingung wird aber nie false, also die 
while-Schleife nie verlassen.

Danke schonmal,
Martin
Moderator Persönliche Seite
Ich würde auf ein Vorzeichenproblem tippen.  Durch die Schiebeoperation
wird der Typ des entsprechenden Ausdrucks nach `int' promoted, und
sobald dann das Bit 7 gesetzt ist, werden die Bits 8...15 auch
gesetzt.

Probiere mal, ob das sich ändert, wenn du explizit mit "5U" schiebst
statt "5".
Ich würde sagen, dass das ein Compilerfehler ist, der optimiert hier 
etwas zu clever. Der Code sieht nämlich so aus:
1
+0000002F:   C001        RJMP    PC+0x0002        Relative jump
2
+00000030:   D006        RCALL   PC+0x0007        Relative call subroutine
3
+00000031:   B380        IN      R24,0x10         In from I/O location
4
+00000032:   3087        CPI     R24,0x07         Compare with immediate
5
+00000033:   F7E1        BRNE    PC-0x03          Branch if not equal
Hallo.
Es gibt auch noch einen interessanten Unterschied: In der ersten Version 
überprüfst du mit Bitoperatoren, ob die unteren 3 Bit gesetzt sind. Das 
ist ok. Die Anderen Bits von PINx spielen dadurch keine rolle.

Bei der unteren Variante, vergleichst du logisch. Dabei zählen alle 
Bits.
Soweit ich weiß, arbeitet der Compiler bei so einem Vergleich mit ganzen 
ints. Also in dem fall 16bit. Das Shift5 löscht somit die anderen bits 
nicht.
Sie werden einfach ins HighByte verschoben. Dein 8bit Konstanten 
ausdruck ist auch ein int. sein HighByte ist 0.
Somit spielen die anderen Bits von PINx plötzlich eine Rolle.
Ich vermute das alles nur ;-) Bitte nicht lachen ;-)
Bei dem gezeigtes ASM weiß ich leider nicht, welche Version das ist. 
vermutlich die untere.. das all mein gebrabbel widerlegen würde :-D

Ich würde es nochmal mit:

while((unsigned char)(((unsigned char)PIND) << 5) != (unsigned 
char)0b11100000){warte();}
probieren. Das ist Nummer sicher ;-)

oder:

while(((PIND&0x07) << 5) != 0b11100000){warte();}

So.
MFG
Gast
Ich kann die Erklärung von Der Albi und Jörg (promotet zu was mit 16bit) 
bestätigen. Habe es jetzt (fast) wie von Der Albi vorgeschlagen:
1
while(( (PIND & 0b00000111) << 5) != 0b11100000){...}

Klappt wunderbar.

Danke Leute!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.