www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik mehrer Bits verschieben


Autor: auf_den_Schlauch_steher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hab eine einfache Frage, komme aber gerade nicht selber drauf.

Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links 
verschieben.

Einzelne Bits in C kann man ja wie folgt verschieben:

Signal[0] << 4; // 1.Bit um 4 nach links verschoben

Nun möchte ich aber die 4.Bit mit einmal verschieben, gibts da eine 
einfache Möglichkeit oder muss ich jedes Bit einzeln verschieben?

Danke

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die restlichn bits werden "mit" verschoben...
allso aus 01010 << 3 wir 01000

Oder meisnt du was anderes?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit einem Shift werden immer alle Bits in der betreffenden Variable 
verschoben. Die Shift-Operatoren besitzen 2 Argumente: dasjenige links 
vom Operator ist die Variable, die geschoben werden soll und rechts 
steht die Anzahl der Stellen, um die geschoben werden soll.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, wenn Du meinen solltest, mit Signal[0] würdest Du auf ein Bit 
einer Variablen namens Signal zugreifen, dann täuschst Du Dich! 
Signal[0] liefert das erste Element eines Arrays (von Variablen des Typs 
XXX). Wenn Signal ein Array von int ist (also z.B.
 int Signal[Array_Laenge]; 
), dann ist Signal[0] auch ein int mit mindestens 16 Bit. 
Dementsprechend werden z.B. bei
Irgendwas = Signal[0] << 4;
auch alle 16 Bit geschoben.

Autor: auf_den_Schlauch_steher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok,

dann ist es doch nicht so einfach.

Wie kann ich denn die ersten 4 Bit aus dem Signal extrahieren, um diese 
zu verschieben?

Ich muss nur, die ersten 4 verschieben und nicht alle.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
variable_2 = variable_1;

variable_2 = variable_2 << 4;

In Variable_2 stehen dann die 4 unteren Bits aus Variable_1, verschoben 
um 4 Stellen.

Innerhalb der gleichen Variable geht das natürlich nicht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auf_den_Schlauch_steher wrote:

> Ich muss nur, die ersten 4 verschieben und nicht alle.

Dann mußt Du die maskieren (AND):

variable = (variable & 0x0F) << n;



Peter

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: auf_den_Schlauch_steher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 => 1111 0110 werden?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Je nach Variablentypus ist die Maskiererei auch Käse, weil, wenn ich in 
nem Byte die unteren vier Bits um vier Stellen nach links verschiebe...

Achso, und Schiebereien um mehrere Positionen mag der GCC+AVR im Übrigen 
garnicht, und erst recht nicht, wenn die Anzahl der zu verschiebenden 
Stellen noch variabel ist:
uint8_t a, b, i;

a = b << 1; /* schnell */
a = b << 4; /* auch noch schnell, weil swap+and in Assembler */
a = b << 3; /* nich-sooooo-gut, aber immer noch schnell */
a = b << i; /* Bullshit, weil Schleife in Assembler */

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@auf_den_Schlauch_steher (Gast)

>Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste

>nachvariable = (variable & 0x0F) << 4;

> z.B. aus 1001 0110 => 1111 0110 werden?

Nö.

Erster Schritt, Maskieren in der Klammer

(variable & 0x0F) = 1001 0110 & 0000 1111 = 0000 0110

Zweiter Schritt, nach Links verschieben, es wird mit Null aufgefüllt

() <<4 = 0000 0110 << 4 = 0110 0000

MFG
Falk

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auf_den_Schlauch_steher wrote:
> Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
>
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 =>
> 1111 0110 werden?

Natürlich nicht.

Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4
0110 0000.


Peter

Autor: meister lampe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4 0110 0000.

richtig.
warum also die maskiererei?

variable <<= 4;

macht das gleiche.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In dem Fall.... . Schieb doch mal mit 3.

Autor: Eddy Current (chrisi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Gott, Michael, das ist doch der Gag, dass man bei 4 Bits schieben 
eben nicht maskieren muss. Und sag jetzt nicht: "Dann mach' das mal mit 
ner 16-Bit-Variable". Dann gibt's eins auf die Nüsse.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist aber dann Compiler-abhängig, oder? Also ich meine, der MSPGCC 
maskiert bei Bedarf selbst, bevor er rotiert....hab das mal im Listung 
gesehn.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian R. wrote:
> Das ist aber dann Compiler-abhängig, oder? Also ich meine, der MSPGCC
> maskiert bei Bedarf selbst, bevor er rotiert....hab das mal im Listung
> gesehn.

Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard 
festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven Pauli wrote:
> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
Sicher??
Also "mein" Standard (C99) sagt:
links shift: es wird IMMER mit 0 aufegführt.
rechts shift: unsinged wird mit 0 aufgefüllt, signed wird mit dem 
sign-bit (negativ = 1, postiv = 0) aufgefüllt!

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi Mail@laeubi.de wrote:
> Sven Pauli wrote:
>> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
>> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
> Sicher??
Ja, sicher...wobei ich jetzt unsigned vorausgesetzt hab :-/ Ansonsten 
sinds halt VZ-Bits, jubb.

Autor: meister lampe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hallo, hab eine einfache Frage, komme aber gerade nicht selber drauf.
> Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links verschieben.

die lösung heisst

unsigned char signal;
signal <<= 4;

over and out.

Autor: Matthias Larisch (matze88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe das gefühl, dass der OP genau das erreichen will, was er in der 
Zwischenfrage gestellt hat:
0100 1001     solll nach der operation zu 1101 ?(0000)? werden.
Das funktioniert wie folgt:

uint8_t a = 0b01001001;
a |= (a << 4);

(falls gewünscht low nibble auf 0 setzen:)
a &= 0xF0;

Ich weiß nicht, was der Compiler daraus macht. aber im Assembler würde 
ich das so lösen:
rE -> Eingangsregister (high register)
rT -> temporäres register

mov rT, rE
swap rT
or rE, rT
andi rE, 0xF0

das gewünschte Ergebnis liegt dann wieder in rE.
Matze

Autor: auf_den_Schlauch_steher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das von Matze scheint das zu seien was ich brauche. Denn nachdem ich die 
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit 
addieren. Sry, dass ich das nicht gleich geschrieben habe, dachte nicht 
das es bei der schiebe Operation von belangen ist.

Ich werde das ganze mal testen und schauen ob es das gewünschte Ergebnis 
liefert.

Autor: Matthias Larisch (matze88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst dich mal bitte auch weiterhin etwas genauer ausdrücken. In 
deinem letzten Post schreibst du:
Denn nachdem ich die
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit
addieren.

2 Sachen: a) "den letzten 4. bit" gibt es nicht. der Punkt hinter der 4 
bedeuted VIERTES Bit und bezieht sich somit auf 1 Bit. Kann eventuell in 
anderer Formulierung zu Unklarheiten führen.

b) Die lieben Grundrechenarten eines Prozessors. Du sprichst hier von 
"addieren". Da besteht ein kleiner aber feiner Unterschied zum Oder:

0b011001011
0b101000101 seien unsere 2 Bytes. Verodert ergibt sich:

0b111001111    addiert ergibt sich aber:
0b000010000 + carry bit set -> 9 bit ergebnis 0b1000010000

wahh ich seh gerade ich hab versehtnlich 9 statt 8 Bits aufgeschrieben, 
aber das Additionsbeispiel ist gerade so toll, ich belasse es einfach 
mal dabei.

Matze (Der eigentlich gerade an seinem Artikel arbeiten sollte, da in 
nichtmal mehr 10 Stunden die Deadline vorbei ist...)

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich hab auch mal eine Frage zum Bitshifting.

Hab eine 16Bit-Variable aus der ein 12Bit-Wert extrahiert werden 
soll.Dieser Wert setzt sich aus den Bits 0 bis 11 zusammen.Wie bekomme 
ich da den Wert nun aus den 16Bit heraus,mit Vorzeichen?!
D.h. in der Spanne von -2046 bis 2045?

hier der Code (beispielhaft):

signed int variable1 = 0x2DAA;

variable1 <<= 4; // Schiebe um 4 Stellen nach links

Der Wert von variable1 bewegt sich aber nun nicht im Bereich von -2046 
bis 2045. Wie bekomm ich das hin?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t sign12( uint16_t i )
{
  if( i & 0x0800 )
    i |= 0xF000;
  return i;
}


Peter

Autor: Denny S. (nightstorm99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe gerade auch ein paar Probleme mit dem Bit bestimmen.

Ich habe ein uint16_t und will nun nur die unteren 3 Bits wissen.
Wie mache ich das?


Gruß Denny

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denny S. schrieb:
> Hallo!
>
> Ich habe gerade auch ein paar Probleme mit dem Bit bestimmen.
>
> Ich habe ein uint16_t und will nun nur die unteren 3 Bits wissen.
> Wie mache ich das?

Indem du eine Maske benutzt, in der die unteren 3 Bits 1 sind und alle 
anderen 0.


  Ergebnis = Variable & 0x0007;

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.