mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Longwert: Bits vertauschen LSB zu MSB


Autor: Andreas Häusler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute

Brauche wieder mal dringend Eure Hilfe.
Muss in einer long Variable (32Bit) alle Bits vertauschen.


      Bit31                              Bit0
Alt:    11110001 11110001 11110001 11110001
Neu:    10001111 10001111 10001111 10001111

Wer kennt die effizienteste Variante?

Danke im Voraus.

Autor: Axel Krüger (axel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eventuell mit Schiebebefehlen unter Benutzung des Carry Bit

edit:  zb r10 - 14 und hilfregister r17

clc  ;clear carry

lsr r14

rol r17

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf einen Rutsch wohl blöd zu machen.

In einzelnen Byte besser.

Ein Byte drehen:
unsigned char umkehr(unsigned char n){
n=((n>>1)&0x55)|((n<<1)&0xaa);
n=((n>>2)&0x33)|((n<<2)&0xcc);
return (n>>4)|(n<<4);
}

Byte 1 mit 4 und 2 mit 3 tauschen.

fertig

avr

Autor: Andreas Häusler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute

Danke für die Info. Hab's jetzt so gelöst:
unsigned char i;
unsigned long mask;
unsigned long tmp_data;
unsigned long reverse_data;

mask = 0x00000001;
reverse_data = 0;

//Longwert spiegeln
for (i=0;i<32;i++)
{
  if((tmp_data & 0x80000000) == 0x80000000)
  {
    reverse_data |= mask << (unsigned long)i;  
    tmp_data = tmp_data << 1;
  }
  else
  {
    reverse_data &= ~(mask << (unsigned long)i);  
    tmp_data = tmp_data << 1;
  }  
} 

Ist vielleicht nicht die beste Lösung, aber es tut.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Häusler schrieb:

> Muss in einer long Variable (32Bit) alle Bits vertauschen.

Welcher Prozessor?

Autor: Stephan Henning (stephan-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bei 4 Bit macht man Nibbletausch.
Warum nicht auf 8 Bit Ebene ? 0 Problem in ASM:

Sonst hilft wohl nur Ringelpietz mit Anfassen :-))
Oder ein Tauschbuffer.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hintergrund meiner Frage: Es gibt Prozessoren, die für sowas nur einen 
Takt benötigen. Weil entsprechender Befehl vorhanden. Ausserdem wurde 
anfangs explizit nach der effizientesten Variante gesucht, nicht - wie 
später - nach irgendeiner.

Autor: Stephan Henning (stephan-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Ausserdem wurde
> anfangs explizit nach der effizientesten Variante gesucht, nicht - wie
> später - nach irgendeiner.

Leider hast Du die Plattform nicht erwähnt. Daher nur Antworten aus der 
Glaskugel. Sorry.
Oder wäre die Antwort

SWAP A

hilfreicher ?

Autor: R. K. (uc_student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich möchte dieses Thema nochmals ein wenig aufwärmen...

Ich portiere gerade ein Programm von einem STM32 auf einen Stellaris uC. 
Dabei ist mir aufgefallen, dass ich bei der SPI-Schnittstelle die Wahl 
von LSB-First nicht mehr habe. Bei den Stellaris ist halt einfach 
MSB-First fix einprogrammiert.

@A.K. könntest du mir vielleicht den Befehl zum drehen eines 16 Bit 
Wortes nennen? Ich stehe da gerade ziemlich auf dem Schlauch.

Besten Dank im Voraus

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde es mal der Suche versuchen...
Und fände dann ganz leicht den 8 Jahre alten 
Beitrag "Re: Bitreihenfolge ändern"
Und den 3 Jahre alten Beitrag "Wie drehe ich eine Bitreihenfolge um??"
Und noch einige mehr...

> R. K. schrieb:
> Bei den Stellaris ist halt einfach MSB-First fix einprogrammiert.
Ja, weil das der Rest der Welt auch so macht...

Autor: R. K. (uc_student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> R. K. schrieb:
>> Bei den Stellaris ist halt einfach MSB-First fix einprogrammiert.
> Ja, weil das der Rest der Welt auch so macht...


Doch genau damit habe ich ein Problem. Ich empfange einen
kontinuielichen Datenstrom. Ich clocke dabei die SPI selbst und
speichere einfach alle empfangenen Bits in einem grossen Buffer. Danach
suche ich in diesem Buffer nach meinem Sync-Wort und decodiere die
Daten.

Da ich asynchron arbeite kann ein Daten-Byte auch über mehre Bytes im
Speicher verteilt sein. Durch die LittleEndian eigenschaft des Cortex
ergeben sich dann deutliche Unschönheiten.

Der DMA füllt beispielsweise den Buffer an der stelle [1] mit dem ersten
Byte. Danach füllt er den Buffer an der stelle [2] mit dem nächsten
Byte... Wenn ich die Daten für eine effiziente Verarbeitung mit
32-Bit-Variablen verarbeiten will krieg ich ein riisen Problem wegen dem
little Endian. Könnte ich die Daten mit LSB first im Speicher ablegen,
so würde das ganze zwar vedreht, jedoch gibt es keine Fehler im
Speicher.

Vielleicht kennst du auch eine Möglickeit, damit der DMA meine 
Byte-Daten so in den Speicher schreibt, damit ich die Daten später als 
32-Bit interpretieren kann?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
R. K. schrieb:
> Ich clocke dabei die SPI selbst und speichere einfach alle empfangenen
> Bits in einem grossen Buffer. Danach suche ich in diesem Buffer nach
> meinem Sync-Wort und decodiere die Daten.
Und warum suchst du nicht während der Übertragung nach dem Sync-Wort 
und speicherst ab dann die Daten? Dann hast du nuch nicht irgendwo 
mitten drin einen Byte- bzw. Wortumbruch, und du weißt sofort wo die 
relevante Information im Speicher liegt.

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wer kennt die effizienteste Variante?

Tabellenzugriff.

Als speed/space tradeoff wohl byteweise.

union
{
    long longvalue;
    unsigned char bytevalue[3];
}
value,newvalue;

unsigned char table[256]={0x00,0x80,0x40,0xC0,...};

newvalue.bytevalue[0]=table[value.bytevalue[3]];
newvalue.bytevalue[1]=table[value.bytevalue[2]];
newvalue.bytevalue[2]=table[value.bytevalue[1]];
newvalue.bytevalue[3]=table[value.bytevalue[0]];

Zumindest auf Prozessoren ohne barrel shifter.

Autor: Uwe Bonnes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Cortex M3/4 kennt den RBIT Befehl:
RBIT: Reverse the bit order in a 32-bit word
Und dazu noch verschiedene REV Befehle, um Bytes zu tauschen. Ist das 
nicht was hier benoetigt wird?

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
for (i=0;i<32;i++)
{
  if((tmp_data & 0x80000000) == 0x80000000)
  {
    reverse_data |= mask << (unsigned long)i;
    tmp_data = tmp_data << 1;
  }
  else
  {
    reverse_data &= ~(mask << (unsigned long)i);
    tmp_data = tmp_data << 1;
  }
}


Das geht aber eleganter (mask ist Maske und Zähler in einem):
data_out=0;mask=0x80000000;do{data_out<<=1;
  if((data&mask)!=0)data_out |= 1;}while((mask>>=1)!=0);

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.