Forum: Mikrocontroller und Digitale Elektronik Verständnissfrage zur Bitverschiebung


von Em G. (exe87)


Lesenswert?

Hallo,
Ich hab eine kleine Verständnisfrage zur Bitverschiebung.
Und zwar will ich ein Byte(8bits) aus einem Rechtecksignal 
vollschreiben.
definition:
1
volatile int zahl=0;
2
volatile int bit;
3
volatile int bit_z;

In der Main:
1
zahl |= (bit<<bit_z);
(bit_z wird danach inkrementiert und wenn er bei 8 ist, wieder auf 0 
gesetzt und das byte beschrieben, so sollte quasi das Byte voll sein)

Nachdem, was ich verstanden habe, sollte doch von rechts angefangen 
werden(also bit_z = 0) und dann immer einen weiter nach links.

Das Problem ist, das ich jedoch zb wenn normal 6 rauskommen sollte, 96 
rauskommt. Ist es dann also doch umgekehrt?
1
zahl |= (bit>>bit_z);

von Fabian O. (xfr)


Lesenswert?

Was heißt "wenn normal 6 rauskommen sollte"? Das niederwertigste Bit 
(Wert 1) ist das ganz rechte, das beschreibst Du als erstes. Das links 
daneben hat Wert 2, das nächste Wert 4 usw.

Wenn der Wert 6 rauskommt, waren das 2. und 3. empfangene Bit 1 und die 
anderen 0.

Dein Algorithmus ist übrigens auf einem Mikrocontroller ohne 
Barrel-Shifter ziemlich ineffizient. Besser wäre:
1
zahl = (zahl << 1) | bit;

Dann ist es aber wirklich "umgekehrt", weil das Bit dann mit jedem 
Durchgang eine Stelle weiter nach links rückt. Das erste empfangene Bit 
steht am Ende also ganz links. Kommt halt drauf an, wie Du es haben 
willst/brauchst.

Die volatiles sind sicher auch nicht alle nötig.

von Em G. (exe87)


Lesenswert?

Die volatiles habe ich wegen einem interrupt und sollten überall 
vorhanden sein, also im interrupt und main(oder ist das falsch?)

Also ich sollte aus einem Rechtecksignal theoretisch die 6 bekommen, 
daher die 6.
Das Rechtecksignal kommt so an:
01100000 (Im Rechtecksignal)
Müsste also quasi wenn von rechts nach links anfängt in das Byte zu 
schreiben so da stehen:
00000110 also 6.
Jedoch ist es genau wie in der Rechtecksignal
01100000 also 96.

Was ist ein Barrel-shifter??

Danke schonmal für die Antwort ;)

von Fabian O. (xfr)


Lesenswert?

Em Gr schrieb:
> Die volatiles habe ich wegen einem interrupt und sollten überall
> vorhanden sein, also im interrupt und main(oder ist das falsch?)

Das volatile brauchst Du nur bei Variablen, die sowohl in main als auch 
im Interrupt verwendet werden. Vermutlich ist das nur bei zahl der Fall. 
bit und bit_z brauchst Du dagegen nur im Interrupt, nicht in main.

> Das Rechtecksignal kommt so an:
> 01100000 (Im Rechtecksignal)

Also kommt zuerst eine Null, dann zwei Mal eine Eins und dann fünf 
Nullen? Und das empfangene Bit steht (als einziges) ganz rechts in der 
Variable bit?

Wenn ja, dann sollte mit diesem Code
1
zahl |= (bit<<bit_z);
2
bit_z++;
das rauskommen:

> Müsste also quasi wenn von rechts nach links anfängt in das Byte zu
> schreiben so da stehen:
> 00000110 also 6.

Wenn etwas anderes rauskommt, lag entweder ein anderes Signal an oder 
der Fehler liegt an anderer Stelle im Code. Poste ihn am besten mal 
komplett.

> Was ist ein Barrel-shifter??

Ein Barrel-Shifter kann einen Wert mit einem Maschinenbefehl um eine 
beliebige Anzahl an Bits verschieben. Auf dem AVR geht das zum Beispiel 
nicht, er kann eine Variable mit einem Befehl nur um eine Stelle 
verschieben. Bei einer variablen Anzahl an Stellen, wie in dieser 
Anweisung
1
zahl |= (bit<<bit_z);
wird der Compiler daraus eine Schleife machen, die bit_z mal läuft und 
bit immer eine Stelle weiter nach links schiebt. Erst danach kann der 
Wert mit zahl verodert werden. Bei meiner Alternative kann das 
Nach-Links-Schieben dagegen jedes Mal mit nur einem Maschinenbefehl 
geschehen.

von spontan (Gast)


Lesenswert?

@Em Gr:

Ich hätte auch eine kleine Verständnisfrage:

Was gibt Dir den Takt vor, wann im Programm geschoben werden soll?


Wenn Du die linken Ziffern des Beispiels (01100000) von rechts in den 
Akku schiebst, dann erhälst Du natürlich dezimal 96. Schieb die bits von 
links auch von links in den Akku und Du erhälst dezimal 6.

von Em G. (exe87)


Lesenswert?

Guten Morgen,
spontan:
Also das Rechtecksignal kommt in der Reihenfolge von links nach rechts 
gelesen an:
01100000 also Dezimal 6.
Also wird dies doch auch im Code so verarbeitet. Erst wird die 0 
erkannt, dann die zwei 1en usw.. Okay, wenn ich dies jetzt von rechts 
nach links über
1
zahl |= (bit<<bit_z);
 in das byte "zahl" schreibe, dann müsste ja dabei 00000110 rauskommen. 
Er fängt ja mit 0 Verschiebungen an, und geht dann weiter bis auf 8 und 
fängt dann wieder bei 0 an.
Das beschriebene Byte "zahl", wird das dann von links nach rechts 
gelesen, also erstes Bit 1 zweites 2 drittes 4,.. oder von rechts nach 
links. Weil dann würde es für mich auch Sinn ergeben, dass er immer 96 
anzeigt.
Sorry, bin gerade ein wenig durcheinander von den ganzen bits.

Fabian O., hier ist der Code:
1
        //count bits
2
        zahl |= (bit<<bit_z);
3
        bit_z++;
4
5
        //set byteflag
6
        if(bit_z==8){
7
          bit_z = 0;
8
          byteflag = 1;
9
        }
10
        else
11
          byteflag = 0;
12
        if(byteflag==1)
13
        {
14
           zahl1 = zahl;
15
        }

von Em G. (exe87)


Angehängte Dateien:

Lesenswert?

Nochmal eine kleine Frage,
Ich habe gerade am Osca gesehen, das er zwischendurch anscheinende 
nochmal einen Interrupt ausslöst.
Wenn ich einen einfach Code, Ausgang = Eingang habe, wird alles ganz 
normal erkannt und nochmal genauso ausgegeben.
Wenn ich das ganze per Interrupt mache hat er zwar das ähnliche Signal, 
jedoch sind zwischendurch diese "Mini Interrupts", wo ich nicht weiss, 
woher die kommen!?

von wire (Gast)


Lesenswert?

Bits sind in bigendian abgelegt. Das niderwertigste Bit (0) steht also 
an höherer Stelle im Speicher. Werte die mehr als ein Byte benötigen 
sind jedoch in littleendian abgelegt, d.h. das niederwertigste Byte 
steht auch an niederer Stelle im Speicher.

Hier ein Artikel dazu:
http://avr.myluna.de/doku.php?id=de:byteorder

wire

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.