Wie drehe ich eine Bitreihenfolge um??

Gast #177677
Lesenswert?

@Jörg Wunsch
Wenn ich wüste wonach genau, wäre die antwort OK. Aber ich kann hier
nicht mehrere hundert/Tausend Beiträge auf gut Glück durchlesen, um
eventuell auf ein ähnliches Prolem zu stossen. Ein Denkanstoss wäre
schon nett, dann kann ich nämlich die SuFu verwenden.


@Christof Krüger
JA.
Gast #177681
Lesenswert?

Ich hab da was aus nem Projekt letztes Semester...

/* for bit_reverse: 3, fo an 8 pt FFT, 4 for 16 pt etc...*/
#define BIT_WIDTH 7

//__________________________FFT specific
functions_______________________________
/* Reversing the bits in an integer. No asm instruction
   available for this -> slow */
int bit_reverse(int in) {
 int rev=0;
 int i;

 for (i = 0; i < BIT_WIDTH; i++) {
  rev = (rev << 1) | (in & 1);
  in >>=1;
 }
 return rev;
}

Mit Bitwidth angeben wie lang (in Bit) der unzudrehende Wert ist. Also
beim AVR z.B. 8 für ein uint8_t oder 16 für einen uint16_t
Gast #1494497
Lesenswert?

also ich muss das selbe mit einer 8 bit zahl machen.

int bit_reverse(int in) {
 int rev=0;
 int i;

 for (i = 0; i < BIT_WIDTH; i++) {
  rev = (rev << 1) | (in & 1);
  in >>=1;
 }
 return rev;
}

Das habe ich einfach von oben übernommen. ich muss dann bitwidth auf 8 
setzen? Mwin größtes problem ist, das ich nicht weiß wie ich die 
funktion in der main aufrufe. Kann mir das jemand sagen?
#1494512
Lesenswert?

Hans Mildenberger schrieb:
> also ich muss das selbe mit einer 8 bit zahl machen.
>
> int bit_reverse(int in) {
>  int rev=0;
>  int i;
>
>  for (i = 0; i < BIT_WIDTH; i++) {
>   rev = (rev << 1) | (in & 1);
>   in >>=1;
>  }
>  return rev;
> }
>
> Das habe ich einfach von oben übernommen. ich muss dann bitwidth auf 8
> setzen? Mwin größtes problem ist, das ich nicht weiß wie ich die
> funktion in der main aufrufe. Kann mir das jemand sagen?

So wie jede andere Funktion auch
1
   ergebnis = bit_reverse( ausgangswert );
Gast #1494529
Lesenswert?

Entschuldige meine delitantische Antwort, aber es geht nicht :-(


int main (int argc, char *argv[])
{
   ausgangswert = 01101100
   ergebnis= bit (ausgangswert);
}
 int bit_reverse(int in) {
  int rev=0;
  int i;

  for (i = 0; i < BIT_WIDTH; i++) {
   rev = (rev << 1) | (in & 1);
   in >>=1;
}
  return rev;
}
#1494534
Lesenswert?

"Es geht nicht" ist keine vernünftige Fehlerbeschreibung.

Wie wäre es mit einem C-Lehrbuch?
1
#define BIT_WIDTH 8
2

3
int bit_reverse(int in) {
4
  int rev=0;
5
  int i;
6

7
  for (i = 0; i < BIT_WIDTH; i++) {
8
   rev = (rev << 1) | (in & 1);
9
   in >>=1;
10
  }
11
  return rev;
12
}
13

14
int main (int argc, char *argv[])
15
{
16
  int ausgangswert = 0b01101100;   // ist nicht Standard C, aber der gcc kanns
17
  int ergebnis = bit_reverse(ausgangswert);
18
}
Gast #1494556
Lesenswert?

Es kommen fogende fehlermeldungen:

invalid suffix "b01100000" on integer contant
In function ínt main(int, char**)´:
ausgabewert undeclared (first use in function)
(Each undeclareded identifier is reported only once for each function it 
appears in.)
bit reverse undeclared (first use in function)
in function int bit_reverse(int):
int bit reverse(int) used prior to declaration
[Build Error] [main.0] Error 1


1000 Dank das ihr euch die Zeit nehmt.
#1494569
Lesenswert?

Hans Mildenberger schrieb:
> dev-c++



Na dann
1
#define BIT_WIDTH 8
2

3
int bit_reverse(int in) {
4
  int rev=0;
5
  int i;
6

7
  for (i = 0; i < BIT_WIDTH; i++) {
8
   rev = (rev << 1) | (in & 1);
9
   in >>=1;
10
  }
11
  return rev;
12
}
13

14
int main (int argc, char *argv[])
15
{
16
  int ausgangswert = 0x6C;   // 01101100
17
  int ergebnis = bit_reverse(ausgangswert);
18
}
Gast #1494578
Lesenswert?

Da bleibt nur noch einer übrig.
Die anderen Fehlermeldungen gehen auch weg, wenn ich einfach das ich 
ausgangswqert = 01100001´; geschrieben hätte.

In function ínt main(int, char**)´:
ausgabewert undeclared (first use in function)
(Each undeclareded identifier is reported only once for each function it
appears in.)
[Build Error] [main.0] Error 1
#1494584
Lesenswert?

Hans Mildenberger schrieb:
> Da bleibt nur noch einer übrig.
> Die anderen Fehlermeldungen gehen auch weg, wenn ich einfach das ich
> ausgangswqert = 01100001´; geschrieben hätte.

Ja. Nur hätte das etwas ganz anderes gemacht als du dir auch nur in 
deinen wildesten Träumen vorstellen kannst.
Oder sagen dir Oktalzahlen irgendetwas :-)

> In function ínt main(int, char**)´:
> ausgabewert undeclared (first use in function)
> (Each undeclareded identifier is reported only once for each function it
> appears in.)
> [Build Error] [main.0] Error 1

Den behebst du jetzt schön selber.
Der Compiler schreibt ja schon hin, was faul ist.
Gast #1496593
Lesenswert?

#define smax 8
#include <stdio.h>
int bit_reverse(int in) {
    int rev=0;
    int i;
    for ( i=0; i < smax; i++)
        {
               rev = (rev << 1 )| (in & 1);
               in >>1;
        }
   return rev;
}


int main(int argc, char *argv[])
{
 int ausgangswert = 0x6C;
 int ergebnis = bit_reverse(ausgangswert);
    while(1)
     {
 printf("ergebnis = %d\n", ergebnis); }
}

So sieht mein Programm inzwischen aus. Läuft auch fehlerfrei. Allerdings 
bekomme ich immer die Ausgabe "ergebnis = 0".
Kann mir das jemand erklären?
Persönliche Seite #1496617
Lesenswert?

Hans Mildenberger schrieb:
> #define smax 8
> #include <stdio.h>
> int bit_reverse(int in) {
>     int rev=0;
>     int i;
>     for ( i=0; i < smax; i++)
>         {
>                rev = (rev << 1 )| (in & 1);
>                in >>1;
>         }
>    return rev;
> }
>
>
> int main(int argc, char *argv[])
> {
>  int ausgangswert = 0x6C;
>  int ergebnis = bit_reverse(ausgangswert);
>     while(1)
>      {
>  printf("ergebnis = %d\n", ergebnis); }
> }
>
> So sieht mein Programm inzwischen aus. Läuft auch fehlerfrei. Allerdings
> bekomme ich immer die Ausgabe "ergebnis = 0".
> Kann mir das jemand erklären?

Wenn du den obigen Code kompilierst, solltest du eine Warnung bekommen:
1
um.c: In function ‘bit_reverse’:
2
um.c:9: warning: statement with no effect

Wenn du Dir dann nochmal Zeile 9 anschaust:
1
                in >>1;

Und mit dem Code von oben vergleichst:
1
                in >>= 1;

Stellst du fest das da ein Zeichen fehlt.

Sebastian
Gast #1496691
Lesenswert?

Die Methode von AVR ist richtig nett (und locker doppelt so schnell wie 
die Schleife), habe ich so noch nicht gesehen, obwohl es eigentlich 
ziemlich logisch ist.
Allerdings nicht unbedingt für Anfänger geeignet, was das Verständnis 
betrifft.
Aber für jemanden der meint er kann schon programmieren eine nette 
Fingerübung zum Nachvollziehen :-)
#1496834
Lesenswert?

Am schönsten gehts aber in 8051 Assembler:
1
                                ;C:  ACC:
2
MIRROR:  MOV C, ACC.1           ;1 76543210
3
         RLC A                  ;7 65432101
4
         MOV ACC.2, C           ;7 65432701
5
         MOV C, ACC.3           ;2 65432701
6
         RLC A                  ;6 54327012
7
         MOV ACC.4, C           ;6 54367012
8
         MOV C, ACC.5           ;3 54367012
9
         RLC A                  ;5 43670123
10
         MOV ACC.6, C           ;5 45670123
11
         SWAP A                 ;5 01234567
12
         RET


Peter
Gast #1496988
Lesenswert?

> Wie drehe ich eine Bitreihenfolge mit WinAVR um??

Man sollte für solche Aufgaben immer eine Funktion verwenden die einen 
anderen Programmierer maximal verwirrt ;-) Just für diesen Zweck habe 
ich vor etwas längerer Zeit folgende C Funktion geschrieben:

1
size_t bit_swap(size_t x, size_t bits)
2
{
3
    return bits ? (x & 1) << (bits - 1) | bit_swap(x >> 1, bits - 1) : 0;
4
}


Mit x übergibt man die zu spiegelnden Daten, mit bits gibt man die 
Anzahl der Bits die gespiegelt werden. Will man nur ein Byte spiegeln 
nimmt man "bit_swap(x, 8)". Man kann aber auch nur zum Beispiel 5 Bits 
spiegeln lassen oder 13, ganz egal...
#1497008
Lesenswert?

klaus schrieb:
> Man sollte für solche Aufgaben immer eine Funktion verwenden die einen
> anderen Programmierer maximal verwirrt ;-) Just für diesen Zweck habe
> ich vor etwas längerer Zeit folgende C Funktion geschrieben:

Ziel verfehlt :-)
Damit kannst du gestandene Lisp Programmierer nicht übertölpeln. Die 
schnallen sofort, dass du eine CAR (na ja) / CDR Zerlegung einer Liste 
von Bits auf C Art machst und aus den bearbeiteten Einzelteilen wieder 
eine neue Liste von Bits zusammensetzt :-)

Frei nach dem Motto:
Eine Liste wird umgedreht indem man die Liste in das erste Element und 
den Rest zerlegt. Dann dreht man den Rest um und hängt das erste Element 
hinten drann.

(Schöne Arbeit!)
Gast #1497040
Lesenswert?

Die Antwort die erwartete war:

size_t bit_swap(size_t x, size_t bits)
{
    return bits ? (x & 1) << (bits - 1) | bit_swap(x >> 1, bits - 1) : 
0;
}

Darauf hätte ich geschrieben:

Und wie sieht -  bit_swap - aus?


usw.
#1497051
Lesenswert?

klaus schrieb:
>
1
> size_t bit_swap(size_t x, size_t bits)
2
> {
3
>     return bits ? (x & 1) << (bits - 1) | bit_swap(x >> 1, bits - 1) :
4
> 0;
5
> }
6
>


Ein sehr schönes Beispiel für die Unsinnigkeit von Rekursionen.
Diese Routine maximiert wirklich alles negative:
- höchster Codeverbrauch
- höchster SRAM-Verbrauch
- höchste Zyklenzahl


Peter
Gast #1497067
Lesenswert?

Die Rekursion ist auch klasse.
Vor allem wenn man einen Hardwarestack mit der maximalen Tiefe von (4?) 
hat :-))
War das nicht bei einigen Microcontrollern so?
Ich denke wir sind uns alle einig. Die Funktionen sind alle nicht so 
einfach verständlich wie die Schleife, aber manchmal muss es einfach 
schneller sein, und da sind durchaus auch Speziallösungen sinnvoll.
Schön waren die Lösungen allemal.

Gruß, Udo
#1497077
Lesenswert?

klaus schrieb:
> Man sollte für solche Aufgaben immer eine Funktion verwenden die einen
> anderen Programmierer maximal verwirrt ;-) Just für diesen Zweck habe
> ich vor etwas längerer Zeit folgende C Funktion geschrieben:
>
>
>
1
> size_t bit_swap(size_t x, size_t bits)
2
> {
3
>     return bits ? (x & 1) << (bits - 1) | bit_swap(x >> 1, bits - 1) :
4
> 0;
5
> }
6
>

Wer auf einem Mikrocontroller rekursive Funktionen programmiert, der 
gehört mindestens erschossen, besser noch sollte er sein Studium 
komplett wiederholen müssen ;-)
Gast #1497111
Lesenswert?

Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Wohin gehst du?
Ins kino.
Was läuft?
Quo vadis!
Was bedeutet das?
Gast #1497259
Lesenswert?

Peter Dannegger schrieb:

> klaus schrieb:
>>
>
>> size_t bit_swap(size_t x, size_t bits)
>> {
>>     return bits ? (x & 1) << (bits - 1) | bit_swap(x >> 1, bits - 1) :
>> 0;
>> }
>>
>
>
> Ein sehr schönes Beispiel für die Unsinnigkeit von Rekursionen.
> Diese Routine maximiert wirklich alles negative:
> - höchster Codeverbrauch
> - höchster SRAM-Verbrauch
> - höchste Zyklenzahl

Rekursionen sind nicht generell unsinnig, sondern werden nur traditio-
nell in manchen Programmiersprachen häufiger genutzt als in anderen.

Da Karl Heinz weiter oben den LISP-Programmierer ins Spiel gebracht hat:
Dieser würde die Funktion (wenn er sich überhaupt in die C-Niederungen
herablässt :)) so schreiben:
1
size_t bit_swap2h(size_t x, size_t bits, size_t r) {
2
  return bits ? bit_swap2h(x>>1, bits-1, r<<1|x&1) : r;
3
}
4

5
size_t bit_swap2(size_t x, size_t bits) {
6
  return bit_swap2h(x, bits, 0);
7
}

Dabei ist bit_swap2h eine Hilfsfunktion, die von bit_swap2 aufgeru-
fen wird. Da der Compiler in diesem Fall die Rekursion auflöst, brauchen
beide Funktionen zusammen ziemlich genau gleich viel Programmbytes,
Datenbytes und Taktzyklen wie die folgende, C-typischere Implementierung
mittels einer Schleife:
1
size_t bit_swap3(size_t x, size_t bits) {
2
  size_t r=0;
3
  while(bits--) {
4
    r = r<<1 | x&1;
5
    x >>= 1;
6
  }
7
  return r;
8
}

Der einzig verbleibende Nachteil der rekursiven Variante ist also, dass
sie für einen C-Only-Programmierer nicht sofort verständlich ist ;-)
Gast #1497367
Lesenswert?

>Der einzig verbleibende Nachteil der rekursiven Variante ist also, dass
>sie für einen C-Only-Programmierer nicht sofort verständlich ist ;-)

Ok, dann zeig mit doch mal den Lisp Interpreter für den AVR oder PIC :-)
und die Ausführungszeit ist auch genausoschnell wie bei der Variante von 
Peter :-))))

Gruß und Spass, Udo

Merke: nicht jeder nicht-Lisp-Fan ist ein C-Only-Programmierer oder die 
Crux mit der hinreichenden und notwendigen Voraussetzung :-))
Gast #1497576
Lesenswert?

Udo R. S. schrieb:
>> Der einzig verbleibende Nachteil der rekursiven Variante ist also,
>> dass sie für einen C-Only-Programmierer nicht sofort verständlich ist
>> ;-)
>
> Ok, dann zeig mit doch mal den Lisp Interpreter für den AVR oder PIC
> :-) und die Ausführungszeit ist auch genausoschnell wie bei der
> Variante von Peter :-))))

Ich habe ja nicht dafür plädiert, auf AVRs und PICs in LISP zu program-
mieren, sondern wollte nur aufzeigen, dass rekursive Programmierung —
richtig eingesetzt — bzgl. der von Peter genannten Kriterien nicht
schlechter als iterative Programmierung sein muss.

Ich behaupte aber auch nicht, dass sie besser ist ;-)

(nicht, dass jetzt alle Programmiereinsteiger meinen, sie dürften keine
Schleifen mehr verwenden)
Gast #1501463
Lesenswert?

Ist es möglich den Code von Peter noch zu beschleunigen?

                                ;C:  ACC:
MIRROR:  MOV C, ACC.1           ;1 76543210
         RLC A                  ;7 65432101
         MOV ACC.2, C           ;7 65432701
         MOV C, ACC.3           ;2 65432701
         RLC A                  ;6 54327012
         MOV ACC.4, C           ;6 54367012
         MOV C, ACC.5           ;3 54367012
         RLC A                  ;5 43670123
         MOV ACC.6, C           ;5 45670123
         SWAP A                 ;5 01234567
         RET
#1501799
Lesenswert?

Martin schrieb:
> Ist es möglich den Code von Peter noch zu beschleunigen?
1
;Input:  A
2
;Output: A
3

4
;1.Brute force: 6 / 8 Cycle, 259 Byte
5
MIRROR1:
6
  JZ MIRR1    ;0: leave unchanged
7
  MOVC A, @A+PC    ;mirror 1 to 0FFh (max 255 entries in table!)
8
MIRR1:
9
  RET
10
  MB SET 1
11
  REPT 255    ;use Keil Assembler to expand this macro
12
    DB ((MB AND 1) SHL 7)+((MB AND 2) SHL 5)+((MB AND 4) SHL 3)+((MB AND 8) SHL 1)+((MB AND 10h) SHR 1)+((MB AND 20h) SHR 3)+((MB AND 40h) SHR 5)+((MB AND 80h) SHR 7)
13
    MB SET MB + 1    ;;count up to mirror next byte
14
  ENDM
15

16
;2.Code optimized: 54 Cycle, 10 Byte
17
MIRROR2:
18
  MOV R2, #8    ;all 8 Bits
19
MIRR2:
20
  RLC A      ;shift out
21
  XCH A, R3
22
  RRC A      ;shift in in reverse order
23
  XCH A, R3
24
  DJNZ R2 MIRR2
25
  MOV A, R3    ;get result
26
  RET
27

28
;3.Intelligent: 17 Cycle, 17 Byte
29
        ;C:  ACC:
30
MIRROR3:
31
  MOV C, ACC.1    ;1 76543210
32
  RLC A      ;7 65432101
33
  MOV ACC.2, C    ;7 65432701
34
  MOV C, ACC.3    ;2 65432701
35
  RLC A      ;6 54327012
36
  MOV ACC.4, C    ;6 54367012
37
  MOV C, ACC.5    ;3 54367012
38
  RLC A      ;5 43670123
39
  MOV ACC.6, C    ;5 45670123
40
  SWAP A      ;5 01234567
41
  RET


Peter
Gast #1501803
Lesenswert?

es geht doch mit sehr viel weniger code

out porta, R16
in R16, portb

jetzt nur

PinA0 mit PinB7
PinA1 mit PinB6
PinA2 mit PinB5
PinA3 mit PinB4
PinA4 mit PinB3
PinA5 mit PinB2
PinA6 mit PinB1
PinA7 mit PinB0

verbinden und fertig.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren