Forum: Mikrocontroller und Digitale Elektronik Gibt es etwas wie "(0 << BIT7)"?


von Neuling (Gast)


Lesenswert?

Hallo,

man kann im AVR Studio ja ein Bit mit Einsern in der Form (1 << 
Position) laden. Gibt es das auch umgekehrt?

Bzw gibt es eine bessere möglichkeit ein Port einzulesen und ein 
bestimmtes, aber per Variable definiertes Bit, auf Null zu setzen? Mit
IN temp, PORTX
ANDI temp, 0b11101111
OUT ...
geht es zwar, aber die Position der Null ist festgelegt und nicht per 
(Präprozessor-)Variable definierbar.


Danke für Hilfe

von Karl H. (kbuchegg)


Lesenswert?

Neuling schrieb:

> IN temp, PORTX
> ANDI temp, 0b11101111
> OUT ...
> geht es zwar, aber die Position der Null ist festgelegt und nicht per
> (Präprozessor-)Variable definierbar.

ABer 0b11101111 ist ja nichts anderes als die binäre Umkehrung (aus 0 
mach 1, aus 1 mach 0) von 0b00010000. Und das wiederrum ist ja nichts 
anders als (1<<PD4).

D.h. du brauchst die Operation die im Präprozessor einfach diese 
Umkehrung macht. Das wiederrum macht das Symbol '~'.

Aber. Wenn du sowieso in Assembler nur 1 BIt an einem Port setzen bzw. 
löschen willst, warum benutzt du dann nicht ganz einfach die 
Spezialbefehle, die Atmel ihren AVR Prozessoren spendiert hat?

Siehe AVR-Tutorial

(0<<PD4) ist soweit keine sinnvolle Operation. Denn was macht denn das 
<< ?
Das ist eine Schiebeoperation.
Bei (1<<PD4) wäre das sinnvoll. PD4 ist ja nichts anderes als eine 
andere Schreibweise für 4. D.h. da steht
1
    1 << 4
und das bedeutet einfach nur, dass eine binäre 1
1
   0000 0001
um 4 BIts nach links geschoben wird
1
  0000 0001     Original
2
  0000 0010     1 mal verschoben
3
  0000 0100     2 mal verschoben
4
  0000 1000     3 mal verschoben
5
  0001 0000     4 mal verschoben
d.h. das 1 Bit im Original wandert sukzessive nach links.

Jetzt mach das mal mit 0 << PD4
1
  0000 0000     Original
2
  0000 0000     1 mal verschoben
3
  0000 0000     2 mal verschoben
4
  0000 0000     3 mal verschoben
5
  0000 0000     4 mal verschoben
da entsteht genau dasselbe wie im Original. Einen Wert von 0 nach links 
zu verschieben ist daher eine sonnlose Operation, weil sich nichts 
ändert. Das Ergebnis ist genauso einfach 0, wie es das Original war.

von Neuling (Gast)


Lesenswert?

Genial, Danke!
Nach genau so einem Trick habe ich gesucht!

Ich gehe davon aus, dass es dann so aussehen muss
 ANDI temp, ~(1 << STAT0_PWRKEY)
 STS STAT0, temp
richtig?

SBI/CBI sind mir bekannt, aber wie man oben schon sieht, sind es nicht 
nur I/Os, sondern eben auch SRAMs bei denen einzelne Bits 
gesetzt/gelöscht werden sollen.

von LostInMusic (Gast)


Lesenswert?

1<<0 = 0b00000001
1<<1 = 0b00000010
1<<2 = 0b00000100
1<<3 = 0b00001000
1<<4 = 0b00010000
1<<5 = 0b00100000
1<<6 = 0b01000000
1<<7 = 0b10000000

~(1<<0) = 0b11111110
~(1<<1) = 0b11111101
~(1<<2) = 0b11111011
~(1<<3) = 0b11110111
~(1<<4) = 0b11101111
~(1<<5) = 0b11011111
~(1<<6) = 0b10111111
~(1<<7) = 0b01111111

von Neuling (Gast)


Lesenswert?

Nachtrag zum Nachtrag von kbuchegg

Ich dachte quasi an sowas
1
1111 1111 Orig.
2
1111 1110 Null laden
3
1111 1101 ROL
4
1111 1011 ROL
5
...

von Amateur (Gast)


Lesenswert?

Sieben Mal Nix bleibt nix.

Du kannst aber jedes beliebige Einser-Muster erzeugen und invertieren.
So stellt Dir der Präprozessor auch Dein 00010000 zur Verfügung.

von Amateur (Gast)


Lesenswert?

Sorry, nach der Invertierung natürlich 11101111.

von Karl H. (kbuchegg)


Lesenswert?

Neuling schrieb:
> Nachtrag zum Nachtrag von /kbuchegg/
>
> Ich dachte quasi an sowas
>
1
> 1111 1111 Orig.
2
> 1111 1110 Null laden
3
> 1111 1101 ROL
4
> 1111 1011 ROL
5
> ...
6
>

Kannst du auch machen - wenn du dem Assembler beibringen könntest einen 
ROL zur Assemblierzeit zu machen :-)

Die << Operation füllt rechts immer mit 0 Bits auf. Daher geht dein 
Ansatz nicht.

von Lenny D. (le-do)


Lesenswert?

Selber Effekt, aber man überliest nicht die Tilde:
1
0xFF^(1<<PD4)
Wobei ich zugeben muss, ich würde mich auch eher für die Tilde 
entscheiden...

von Icke ®. (49636b65)


Lesenswert?

Karl Heinz schrieb:
> Einen Wert von 0 nach links
> zu verschieben ist daher eine sonnlose Operation

Logisch erfüllt es keinen Zweck, richtig. In bestimmten Fällen wende ich 
das "Schieben" einer Null wegen der Lesbarkeit des Codes trotzdem an. 
Zum Beispiel beim Setzen der Prescaler-Bits im Timer:

sbr  temp, (0<<CS22)|(0<<CS21)|(1<<CS20)    ;Vorteiler

So sieht man auf den ersten Blick, welche Bits gesetzt sind und welche 
nicht. Außerdem lassen sich schnell Änderungen vornehmen.

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.