Forum: Mikrocontroller und Digitale Elektronik Arduino Bit Shifting Problem


von Michael R. (michael_r288)


Lesenswert?

Hallo liebe Freunde habe kein kleines Problem möchte gerne einen String 
den ich ausgelesen habe folgendermaßen verändern

1
Quell String 80482780C1
2
80    48    27    80    C1
3
10000000  10010000  00100111  10000000  11000001
4
5
6
Ziel String 0112E40183
7
01    12    E4    01    83
8
00000001  00010010  11100100  00000001  10000011

Der String wurder Seriell ausgelesen nun stehe ich da und weiss nicht 
weiter !

von Nils (Gast)


Lesenswert?

Bis auf das zweite Byte sind das alles Bit-Reverse Operationen.

Bist Du sicher, das die Darstellung vom zweiten Byte richtig ist?

von Joe F. (easylife)


Lesenswert?

Nils schrieb:
> Bis auf das zweite Byte sind das alles Bit-Reverse Operationen.

Genau. Die Funktion

y = bitrev(x);

dreht dir ein einzelnes Byte entsprechend um.

von Sven K. (quotschmacher)


Lesenswert?

und wo kommt die bitrev-funktion her?

von Michael R. (michael_r288)


Lesenswert?

das frage ich mich auch gerade da sie nicht in der Referenz erwähnt 
wird.


hier mal mein ganzer code
1
#include <Arduino.h> 
2
#include <hd44780.h>
3
#include <hd44780ioClass/hd44780_pinIO.h>
4
5
6
//Display PinSetup
7
//const int rs = 12, en = 11, db4 = 10, db5 = 9, db6 = 8, db7 = 7;
8
//Piazo Pin Setup
9
const int buzzer = 2;
10
int PowerOn = 0;
11
hd44780_pinIO lcd(12, 11, 10, 9, 8, 7);
12
const int LCDCols = 20;
13
const int LCDRow = 4;
14
15
#define LCD_COLS 20
16
#define LCD_ROWS 4
17
#define HD44780_LCDOBJECT
18
19
20
21
String HITAG1 = "h";
22
String HITAG2 = "H";
23
String EM4102 = "U";
24
String EM4150 = "T";
25
26
27
String ver;
28
String id;
29
String lastscan;
30
String idshort;
31
String MTid;
32
33
void setup()   { 
34
                    pinMode(buzzer, OUTPUT);
35
                    Serial1.begin(9600);
36
                    Serial1.setTimeout(50);
37
                    lcd.begin(20, 4);
38
                }
39
                                
40
41
42
43
44
45
void loop() 
46
                        {   
47
                            if ( ( (PowerOn) == 1 ) && ( (ver.length()) >= 4 ) )
48
                                {
49
                                    Scannen();
50
                                }
51
                            else VersionCheck();
52
53
54
                        }
55
56
//Ruft die Version des Kekses ab und Speichert ihn als String ver
57
String VersionCheck ()      {   Serial.println("Version");
58
                                digitalWrite(buzzer, HIGH);
59
                                delay(800);
60
                                digitalWrite(buzzer, LOW);
61
                                lcd.print ("Scanner 01");
62
                                lcd.setCursor(0,1);
63
                                Serial1.write("v");
64
                                while (!Serial1.available())
65
                                {
66
                                }
67
                                ver = Serial1.readString();                      
68
                                ver.trim();
69
                                lcd.print(String(ver));
70
                                delay(1500);
71
                                PowerOn=1;
72
                                return (ver);
73
                            }
74
75
76
77
//Scannt die ID und übergibt den String
78
String Scannen()
79
                        {
80
                                        Serial1.write("rid");
81
  
82
                                        while (!Serial1.available())
83
                                        {
84
                                        Serial.println("while");
85
86
                                        }
87
88
                                        id = Serial1.readString();                      
89
                                        id.trim();
90
                                        Serial.println(id);
91
                                        
92
                                        Serial1.flush();
93
94
                                        if ((id.length()) > 4 && id != lastscan )
95
                                                
96
                                                {
97
                                                    lcd.setCursor(0,1);
98
                                                    lcd.print("                  ");
99
                                                    lcd.setCursor(0,1);
100
                                                    digitalWrite(buzzer, HIGH);
101
                                                    delay(50);
102
                                                    digitalWrite(buzzer, LOW);
103
                                                    lcd.print("ID:" + id);
104
                                                    lcd.setCursor(0,1);
105
                                                    Serial.println("SCAN1");
106
                                                    idshort = id;
107
                                                    idshort.remove(0,1);
108
109
110
111
112
113
114
115
116
                                                    
117
                                                    if ( id.startsWith(HITAG1) )
118
119
                                                                {
120
                                                                    lcd.setCursor(0,3);
121
                                                                    lcd.print("Typ: HITAG 1");
122
                                                                    lcd.setCursor(0,1);
123
                                                                }
124
                                                    
125
                                                    else if ( id.startsWith(HITAG2) )
126
127
                                                                {
128
                                                                    lcd.setCursor(0,3);
129
                                                                    lcd.print("Typ: HITAG 2");
130
                                                                    lcd.setCursor(0,1);
131
                                                                }
132
133
                                                    else if ( id.startsWith(EM4102) )
134
135
                                                                {   
136
                                                                    lcd.setCursor(0,2);
137
                                                                    lcd.print("MTID:" + byte0i);
138
                                                                    lcd.setCursor(0,3);
139
                                                                    lcd.print("Typ: EM4102");
140
                                                                    lcd.setCursor(0,1);
141
                                                                }
142
                                                    else if ( id.startsWith(EM4150) )
143
144
                                                                {
145
                                                                    lcd.setCursor(0,3);
146
                                                                    lcd.print("Typ: EM4150");
147
                                                                    lcd.setCursor(0,1);
148
                                                                }
149
                                                    
150
                                                    else        {
151
                                                                    lcd.setCursor(0,3);
152
                                                                    lcd.print("Typ: UNBEKANNT");
153
                                                                    lcd.setCursor(0,1);
154
                                                                }
155
156
                                                }
157
158
159
160
                                        else if ( ((id.length()) <= 4 ) && id != lastscan)
161
                                                {
162
                                                            lcd.setCursor(0,1);
163
                                                            lcd.print("KEIN TAG ERKANNT!");
164
                                                            lcd.setCursor(0,3);
165
                                                            lcd.print("                    ");
166
                                                            lcd.setCursor(0,1);
167
                                                }
168
169
                                        
170
171
                                        lastscan = id;
172
                                        
173
                                        return id;
174
                                
175
                        }

: Bearbeitet durch User
von Sven K. (quotschmacher)


Lesenswert?

hier wäre eine solche btirev-funktion, aber ich möchte mal tippen: nicht 
in den standard arduino funktionen...

https://github.com/volthouse/hardware-firmware-arduino/blob/master/DL0815/libraries/Sensirion/Sensirion.cpp 
(ganz unten)

edit: code als anhang und nicht im post selber

: Bearbeitet durch User
von Route_66 H. (route_66)


Lesenswert?

Nils schrieb:
> Bis auf das zweite Byte sind das alles Bit-Reverse Operationen.

Das zweite Byte ist bereits im Quellstring falsch in der 
Bit-Darstellung.
Wenn man 48h richtig als 01001000b darstellt, stimmt auch das Ziel-Byte 
12h (00010010b).

von Michael R. (michael_r288)


Lesenswert?

ja hast recht verhauen aber scheint ja klar zu sein was ich vor habe 
bitrev ist in keinster weise verfügbar leider. grrrr

von Ingo L. (corrtexx)


Lesenswert?

Selbst für einen Arduino-Programmierer sollte es möglich sein, eine so 
banale Funktion schnell selber zu schreiben:
1
uint8_t MirrorByte ( uint8_t ToMirrorByte ){
2
 uint8_t MirroredByte = 0;
3
 for (uint8_t BitNr = 0; BitNr < 8; BitNr++){
4
    if ( ToMirrorByte & (1<<BitNr)) MirroredByte |= (1<<(7-BitNr));
5
 }
6
 return MirroredByte;
7
}

Quick&Dirty

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Quick&Dirty

Geht einfacher:

Beitrag "Re: LCD Datenleitungen invertieren"

MfG Spess

von Ingo L. (corrtexx)


Lesenswert?

spess53 schrieb:
> Geht einfacher:
Einfacher liegt hier im Auge des Betrachters. Einfacher finde ich meine 
Version, deine könnte dafür aber schneller sein.

von spess53 (Gast)


Lesenswert?

Hi

...deine könnte dafür aber schneller sein.

Ist nicht meine. Ich wusste nur das es das Problem hier schon mal gab.

MfG Spess

von Ingo L. (corrtexx)


Lesenswert?

spess53 schrieb:
> Ist nicht meine. Ich wusste nur das es das Problem hier schon mal gab.
Stimmt, is von PeDa. Aber er scheint bekannt dafür, dass sein Code nicht 
auf Anhieb ersichtlich is ;)

Hatte mich schon gewundert das du C programmierst, du bist doch ASM 
Spezi nicht wahr?

von spess53 (Gast)


Lesenswert?

Hi

>Hatte mich schon gewundert das du C programmierst, du bist doch ASM
>Spezi nicht wahr?

Na ja. Manchmal kommt auch C-Spezies etwas brauchbares. Eine 
ASM-Umsetzung dieses Codes habe ich in meiner Mathe Lib.

MfG Spess

von Wolfgang (Gast)


Lesenswert?

Michael R. schrieb:
> ja hast recht verhauen aber scheint ja klar zu sein was ich vor habe
> bitrev ist in keinster weise verfügbar leider. grrrr

Dann solltest du darüber nachdenken, selber eine solche Funktion 
verfügbar zu machen.

Hast du schon mal an selber programmieren gedacht? ;-)

von Route_66 H. (route_66)


Lesenswert?

Ingo L. schrieb:
> Hatte mich schon gewundert das du C programmierst, du bist doch ASM
> Spezi nicht wahr?

In ASM ist das Problem ja so trivial lösbar...
8mal ROL und ROR in einer Schleife geht rasend schnell.

von spess53 (Gast)


Lesenswert?

Hi

>In ASM ist das Problem ja so trivial lösbar...
>8mal ROL und ROR in einer Schleife geht rasend schnell.

Also mindestens 24 Befehle + Kleinkram.

Da ist PeDas Routine kürzer und schneller

[avrasm]
mirror_fast:          push r17
                      swap r16
                      mov r17,r16

                      lsr r16
                      lsr r16
                      lsl r17
                      lsl r17
                      andi r16,$33
                      andi r17,$CC

                      or r16,r17
                      mov r17,r16

                      lsr r16
                      lsl r17
                      andi r16,$55
                      andi r17,$AA
                      or r16,r17
                      pop r17
                      ret

[{avrasm]


MfG Spess

von Über den Dingen (Gast)


Lesenswert?

Man betrachte den Titel:  Arduino Bit Shifting Problem

- Es stellt sich heraus dass das Anliegen nichts mit
Bit shiften zu tun hat.

- es darf gefragt werden was denn Arduino mit Bit
Shifting zu tun hat (klingt nach: "der Arduino kann
nicht Bit shiften").

- der TO ist nicht fähig die Hinweise zum Posten von
Quelltext zu lesen und umzusetzen.

Da geht es in einem Thread drunter und drüber, was für
eine verquere Welt .....

von spess53 (Gast)


Lesenswert?

Hi

Über den Dingen (Gast) schrieb

>- Es stellt sich heraus dass das Anliegen nichts mit
>  Bit shiften zu tun hat.

Wieso nicht? In allen vorgestellten Lösungen wird 'geshiftet'.

Der Rest von dir ist genauso daneben.

MfG Spess

von Route_66 H. (route_66)


Angehängte Dateien:

Lesenswert?

spess53 schrieb:
> Also mindestens 24 Befehle + Kleinkram.
>
> Da ist PeDas Routine kürzer und schneller

Beides Erstere bezweifele ich.
Zu "schneller" muss ich mal die Takte zählen!

von Ingo L. (corrtexx)


Lesenswert?

Route_66 H. schrieb:
> Zu "schneller" muss ich mal die Takte zählen!
Und dafür müsstest du die tatsächliche Zielhardware kennen... Dein 
AVR-ASM funktioniert auf nem AVR, es mag aber auch sein das er einen 
Arduino mit nem 32-Bitter verwendet. Daher wäre hier eine Lösung in C 
angesagt, wie von mir oder Spess, dein ASM hilft hier unter Umständen 
dem TE nicht weiter...

von Route_66 H. (route_66)


Lesenswert?

O.K.
Pedas Variante ist schneller, egal auf welcher Hardware!

Drei Vertauschungen sind effektiver als 8 mal Hin- und Herschieben.

Der TE sollte das Prinzip verstehen, und selbst für seine Hardware und 
Softwareumgebung umsetzen.

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Route_66 H. schrieb:
> Der TE sollte das Prinzip verstehen
Oder er erschlägt das Problem "Brute-Force":
1
 uint8_t MirrorByte ( const uint8_t ToMirrorByte ){
2
  uint8_t MirroredByte = 0;
3
  for (uint8_t BitNr = 0; BitNr < 8; BitNr++){
4
     if ( ToMirrorByte & (1<<BitNr)) MirroredByte |= (1<<(7-BitNr));
5
  }
6
  return MirroredByte;
7
}

: Bearbeitet durch User
von Route_66 H. (route_66)


Lesenswert?

Ingo L. schrieb:
> Oder er erschlägt das Problem "Brute-Force":

Da möchte ich gern mal den ASM-Output des so genialen Compilers sehen!
(c-hater sicher auch?)

von Ingo L. (corrtexx)


Lesenswert?

OK: AVR-GCC9.2.0, Optimierung = Os
1
uint8_t MirrorByte ( const uint8_t ToMirrorByte ){
2
  52:  cf 93         push  r28
3
  54:  df 93         push  r29
4
  56:  30 e0         ldi  r19, 0x00  ; 0
5
  58:  20 e0         ldi  r18, 0x00  ; 0
6
  uint8_t MirroredByte = 0;
7
  5a:  90 e0         ldi  r25, 0x00  ; 0
8
  for (uint8_t BitNr = 0; BitNr < 8; BitNr++){
9
    if ( ToMirrorByte & (1<<BitNr)) MirroredByte |= (1<<(7-BitNr));
10
  5c:  48 2f         mov  r20, r24
11
  5e:  50 e0         ldi  r21, 0x00  ; 0
12
  60:  67 e0         ldi  r22, 0x07  ; 7
13
  62:  70 e0         ldi  r23, 0x00  ; 0
14
  64:  e1 e0         ldi  r30, 0x01  ; 1
15
  66:  f0 e0         ldi  r31, 0x00  ; 0
16
  68:  da 01         movw  r26, r20
17
  6a:  02 2e         mov  r0, r18
18
  6c:  02 c0         rjmp  .+4        ; 0x72 <MirrorByte+0x20>
19
  6e:  b5 95         asr  r27
20
  70:  a7 95         ror  r26
21
  72:  0a 94         dec  r0
22
  74:  e2 f7         brpl  .-8        ; 0x6e <MirrorByte+0x1c>
23
  76:  a0 ff         sbrs  r26, 0
24
  78:  0a c0         rjmp  .+20       ; 0x8e <MirrorByte+0x3c>
25
  7a:  db 01         movw  r26, r22
26
  7c:  a2 1b         sub  r26, r18
27
  7e:  b3 0b         sbc  r27, r19
28
  80:  ef 01         movw  r28, r30
29
  82:  02 c0         rjmp  .+4        ; 0x88 <MirrorByte+0x36>
30
  84:  cc 0f         add  r28, r28
31
  86:  dd 1f         adc  r29, r29
32
  88:  aa 95         dec  r26
33
  8a:  e2 f7         brpl  .-8        ; 0x84 <MirrorByte+0x32>
34
  8c:  9c 2b         or  r25, r28
35
  for (uint8_t BitNr = 0; BitNr < 8; BitNr++){
36
  8e:  2f 5f         subi  r18, 0xFF  ; 255
37
  90:  3f 4f         sbci  r19, 0xFF  ; 255
38
  92:  28 30         cpi  r18, 0x08  ; 8
39
  94:  31 05         cpc  r19, r1
40
  96:  41 f7         brne  .-48       ; 0x68 <MirrorByte+0x16>
41
  }
42
  return MirroredByte;
43
}
44
  98:  89 2f         mov  r24, r25
45
  9a:  df 91         pop  r29
46
  9c:  cf 91         pop  r28
47
  9e:  08 95         ret

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

AVR-GCC9.2.0, Optimierung = O3
1
uint8_t MirrorByte ( const uint8_t ToMirrorByte ){
2
  uint8_t MirroredByte = 0;
3
  for (uint8_t BitNr = 0; BitNr < 8; BitNr++){
4
  cc:  83 2f         mov  r24, r19
5
  ce:  90 e0         ldi  r25, 0x00  ; 0
6
    if ( ToMirrorByte & (1<<BitNr)) MirroredByte |= (1<<(7-BitNr));
7
  d0:  23 2f         mov  r18, r19
8
  d2:  21 70         andi  r18, 0x01  ; 1
9
  d4:  30 fd         sbrc  r19, 0
10
  d6:  20 e8         ldi  r18, 0x80  ; 128
11
  d8:  81 fd         sbrc  r24, 1
12
  da:  20 64         ori  r18, 0x40  ; 64
13
  dc:  82 fd         sbrc  r24, 2
14
  de:  20 62         ori  r18, 0x20  ; 32
15
  e0:  83 fd         sbrc  r24, 3
16
  e2:  20 61         ori  r18, 0x10  ; 16
17
  e4:  84 fd         sbrc  r24, 4
18
  e6:  28 60         ori  r18, 0x08  ; 8
19
  e8:  85 fd         sbrc  r24, 5
20
  ea:  24 60         ori  r18, 0x04  ; 4
21
  ec:  86 fd         sbrc  r24, 6
22
  ee:  22 60         ori  r18, 0x02  ; 2
23
  f0:  88 0f         add  r24, r24
24
  f2:  89 2f         mov  r24, r25
25
  f4:  88 1f         adc  r24, r24
26
  f6:  99 0b         sbc  r25, r25
27
  f8:  89 2b         or  r24, r25
28
  fa:  09 f0         breq  .+2        ; 0xfe <__stack+0x5f>
29
  fc:  21 60         ori  r18, 0x01  ; 1
30
  Dummy2 = MirrorByte( Dummy1 );
31
  fe:  20 93 65 00   sts  0x0065, r18  ; 0x800065 <Dummy2>
32
}

von Ingo L. (corrtexx)


Lesenswert?

Ich muss gestehen das in O3 das Ganze ziemlich exakt das ist, was der C 
auch macht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ingo L. schrieb:
> OK: AVR-GCC9.2.0, Optimierung = Os

Auch zu groß. Lesbare und verständliche Alternative zu PeDas Code:
1
uint8_t mirror (uint8_t b)
2
{
3
    uint8_t nb = 0;
4
5
    if (b & 0x01) nb |= 0x80;
6
    if (b & 0x02) nb |= 0x40;
7
    if (b & 0x04) nb |= 0x20;
8
    if (b & 0x08) nb |= 0x10;
9
    if (b & 0x10) nb |= 0x08;
10
    if (b & 0x20) nb |= 0x04;
11
    if (b & 0x40) nb |= 0x02;
12
    if (b & 0x80) nb |= 0x01;
13
    return nb;
14
}

Eigentlich ist das nix anderes als eine ausgerollte Schleife.
Größe der Funktion mit avr-gcc 4.7.2 -Os: 42 Bytes.

von Ingo L. (corrtexx)


Lesenswert?

Frank M. schrieb:
> Eigentlich ist das nix anderes als eine ausgerollte Schleife.
Eben, die eingerollte Schleife dazu schrieb ich bereits weiter oben

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ingo L. schrieb:
> Frank M. schrieb:
> Eigentlich ist das nix anderes als eine ausgerollte Schleife.
>
> Eben, die eingerollte Schleife dazu schrieb ich bereits weiter oben

Der Witz ist: Die eingerollte braucht mehr Bytes an Code als die 
ausgerollte.
Aus Deiner LSS lese ich: 50 Bytes, aus meiner LSS lese ich: 42 Bytes.

Die Schleife lohnt sich also erst bei größeren Bitbreiten als 8. Aber 
auch da gibt es für 16Bit und 32 Bits Alternativen, zum Beispiel diese 
hier:
1
uint32_t reverse(uint32_t x, int bits)
2
{
3
    x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1); // Swap _<>_
4
    x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2); // Swap __<>__
5
    x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4); // Swap ____<>____
6
    x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8); // Swap ...
7
    x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16); // Swap ...
8
    return x >> (32 - bits);
9
}

Zu diesem Thema gabs hier auch schon einen ausführlichen Thread - inkl. 
Lösungsvorschläge über Lookup-Tables (für Nibbles), um so schnell wie 
möglich zu sein.

von (Gast)


Lesenswert?

ARM Cortex M3 aufwärts hätte "rbit" 
http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABJJDDB.html
das kehrt die Bit-Reihenfolge in einem 32Bit-Wort um.

von Ingo L. (corrtexx)


Lesenswert?

Der M3 hat auch einen Barrel-Shifter. Der AVR nicht

von Ingo L. (corrtexx)


Lesenswert?

Geh ich recht in der Annahme, dass du Route_66 H, überrascht bist, dass 
das, was der Compiler generiert, doch ganz ok ist, sodass du nun auf C 
umgestiegen bist?


SCNR

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.