PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bits auf uC effektiv abfragen



ChristofK
14.06.2011, 13:53
Guten Tag,
ich zerbreche mir gerade ziemlich den Kopf.
Ich habe ein Array bestehend aus 8 Bytes.
Bei jedem dieser Bytes möchte ich überprüfen ob Bits an !bestimmten! Stellen gesetzt sind oder nicht.
z.B. Array[0]=0b100110
Wenn Bit 1==0, dann
a++
Wenn Bit 2==1, dann
a++,
Wenn Bit 3==0, dann
b++
Wenn Bit 4==1, dann
b++
usw.

Ich würde das mit Bitoperationen(Schieben, Vergleichen) lösen. Aber gibt es für so etwas vielleicht elegantere Lösungswege?
Bei einem Array mit 8 Elementen hat ein uC viel zu schieben.. :)

Viele Grüße

askazo
14.06.2011, 14:24
Du kannst auch direkt auf das entsprechende Bit vergleichen, ohne zu schieben.
Hier mal ein Beispielcode äquivalent zu Deiner Vorgabe:


if ((!array[0] & 0b00000010))
a++;
if (array[0] & 0b00000100)
a++;
if (!(array[0] & 0b00001000))
b++;
if (array[0] & 0b00010000)
b++;


Gruß,
askazo

ChristofK
14.06.2011, 14:29
Hallo askazo,
vielen Dank für die Antwort.
Ja, das weis ich. Doch gibt es da nicht etwas effektiveres, z.B. Modulo oder 2-er-Komplement, etc?
Es wird sich sicherlich schon mal jemand Gedanken zu dem "Problem" gemacht haben. :)

Viele Grüße

askazo
14.06.2011, 14:57
Effektiver als die von mir beschriebene Lösung geht nicht.
Wenn man sich mal den compilierten Assembler-Code von meinem Programm anschaut, macht es folgendes:
- Das array aus dem Speicher laden - 2 Takte (LDS-Anweisung)
- Ein Bit des Wertes abfragen - 1-3 Takte - (SBRS bzw. SBRC)
- Je nachdem, wie das Ergebnis ausfällt, den PC hochzählen - 2 Takte (RJMP)

Du brauchst also maximal 5 Takte um einen Vergleich zu machen. Diese Operationen benötigst Du auf jeden Fall (Laden - Vergleichen - Verzweigen).
Alles, was Du jetzt noch dazubastelst - welche Operation auch immer das sein mag - benötigt nur zusätzliche Rechenzeit.
Effektiver geht's echt nicht...

Gruß,
askazo

Richard
14.06.2011, 19:22
Guten Tag,
ich zerbreche mir gerade ziemlich den Kopf.
Ich habe ein Array bestehend aus 8 Bytes.
Bei jedem dieser Bytes möchte ich überprüfen ob Bits an !bestimmten! Stellen gesetzt sind oder nicht.
z.B. Array[0]=0b100110
Wenn Bit 1==0, dann
a++
Wenn Bit 2==1, dann
a++,
Wenn Bit 3==0, dann
b++
Wenn Bit 4==1, dann
b++
usw.

Ich würde das mit Bitoperationen(Schieben, Vergleichen) lösen. Aber gibt es für so etwas vielleicht elegantere Lösungswege?
Bei einem Array mit 8 Elementen hat ein uC viel zu schieben.. :)

Viele Grüße

Hmm, so ganz ist mir nicht klar was Du willst, aber jede Bit Kombination steht ja für eine Zahl zwischen 0 und 255. Also lese einfach den Port (das array) als Dezimalzahl ein und verzweige z.B. mit der case Funktion wenn 1,2,4,8,16,32,64..........oder wasauchimmer.

Case array (1) : Print "1"
..........
Case array (x) : Print "x"



Gruß Richard

ChristofK
14.06.2011, 21:06
Du brauchst also maximal 5 Takte um einen Vergleich zu machen. Diese Operationen benötigst Du auf jeden Fall (Laden - Vergleichen - Verzweigen).

Das ist ja auch alles korrekt. Nur ergeben 5Takte/Bit*6Bits*8Arrays=240Takte. Bei einem Clock von 30Mhz ist meinuC eine Weile unterwegs.
Vielleicht geht es wenn man die Arrays über Bitmasken verknüpft.
Da muss ich aber mal drüber schlafen. :)



z.B. mit der case Funktion wenn 1,2,4,8,16,32,64..........oder wasauchimmer.

Wäre möglich. Doch sind da viele Kombinationen möglich. Das werden sehr lange switch/case Routinen.

Vielen Dank euch!

Viele Grüße

.:Sebastian:.
14.06.2011, 23:00
Moin

Also besser als mit askazos Lösung wirst du net werden können.
Weil egal wie du es im Source schreibts wird dein Kompilier dir immer in etwa das hinoptimieren.
Selbst die switch und case Sache, wird der Kompiler auf If und else zurückvereinfachen und dann so ähnlich umsetzen.

Du könntest höchstens mit nem geschickten assembler Programm vllt. noch einen Takt einsparen, je nach dem wie man deinen Code umschreiben kann.

Auf der anderen Seite :
240 Takte bei 30mhz (komische Frequenz btw.)
240 / (1/ (30*10^6)) = 8*10^-6s = 8uS
Das sind 8us das heißt du kannst immer noch fast 125000mal pro Sekunde dein Array vergleichen.
Ob das jetzt als "eine Weile unterwegs" gilt überlasse ich mal deiner Definition ;)

Was ich ich dann auch noch frage : Musst du mehrere Bits im selben Byte prüfen ?
Weil das werden dann weniger als 5Takte pro Abfrage, weil du ja nur einmal Laden musst um mehre Bits in dem Byte zu vergleichen.
Sprich du wirst noch etwas schneller.

Wenn dir das nicht reicht solltest du über einen größeren uC nachdenken, oder überlegen ob so viele Vergleiche überhaupt notwendig sind.
Machen vllt. mache Vergleiche andere überflüssig ? Gibts irgendwelche abhängigkeiten der Werte untereinander ?
Allerdings kann dir das keiner sagen, solange wir nicht wissen was warum so verglichen wird.


Gruß
Sebastian

wkrug
15.06.2011, 07:14
In AVR Assembler gäbs noch ein paar Möglichkeiten.

Die nutzung des T-Flags im SREG

BST r16,1
BRTS jump
BST r16,2
BRTS jump1. ; uns so weiter.

Eine andere Möglichkeit wär noch das rollen über das Carry Flag

CLC
ROR r16
BRCS jump
ROR r16
BRCS jump1 ; und so weiter

Da hierbei der Schiebevorgang über das Carry stattfindet, und dieses wieder von der anderen Seite in das gerollte Byte eingeschoben wird, kann man damit auch mehrbytige Zahlen verarbeiten.

Searcher
15.06.2011, 08:26
Leider kenne ich C nicht, jedoch ein Gedanke zum Programm:

Das Byte Array bräuchte vielleicht nicht in den Abfragen auf Bits zurechtgeschoben/maskiert zu werden sondern könnte vorher aufbereitet werden.

zB ein Bit Overlay, das über das Bytearray gelegt wird. Das hätte dann 64 Elemente. Oder man macht ein Byte array mit 64 Elementen, bei dem ein Byte den Bitwert des originalen Arrays enthält.

Würde für die Geschwindigkeit der Abfragen vermutlich nichts bringen - der Code sähe dann aber möglicherweise in Bezug auf die Bittests eleganter aus.

Gruß
Searcher