Hallo zusammen,
ich habe eine uint8_t counter variable, die ich als 4 separate 2bit
counter nutzen möchte.
Ich stehe gerade etwas auf dem schlauch wie ich diese counter am besten
herunterzählen kann.
Bit 0,1 -> Counter 0
Bit 2,3 -> Counter 1
Bit 4,5 -> Counter 2
Bit 6,7 -> Counter 3
jeden Counter möchte ich nun herunterzählen können um "-1", aber auch
nicht kleiner als 0 werden (Überlauf).
Wie mache ich das am geschicktesten?
Viele Grüße,
C-Anfänger
c-anfaenger schrieb:> Wie mache ich das am geschicktesten?
Man nimmt 4 Byte.
Wenn der MC dafür zu knapp an RAM ist, dann ist er auch zu knapp an
Flash, um bei jeder Operation aufwendige AND/OR/Schiebe-Orgien
auszuführen.
Yalu X. schrieb:> uint8_t counter;>> counter = counter & counter<<1 & 0xaa | ~counter & counter>>1 & 0x55;
Hast Du Dir das gerade selbst mal eben hergeleitet oder ist das ein
festes Rezept?
Walter T. schrieb:> Hast Du Dir das gerade selbst mal eben hergeleitet oder ist das ein> festes Rezept?
Ersteres. Rezepte kann ich mir leider schlecht merken ;-)
Die Herleitung ist aber nicht schwer:
1. Wertetabelle aufstellen
2. Daraus logische Terme ableiten und vereinfachen
3. Das Ganze noch etwas schöner machen
Hier ist noch eine leicht geänderte Variante, die die beiden
Maskierungsoperationen zu einer zusammenfasst:
1
uint8_tcounter;
2
3
uint8_ttmp=counter&0xaa;
4
counter=tmp&counter<<1|tmp>>1&~counter;
Irgendwie habe ich das Gefühl, dass man das noch weiter vereinfachen
kann, evtl. unter Verwendung der XOR-Operationen, komme aber nicht
drauf.
Yalu X. schrieb:> 1. Wertetabelle aufstellen
Achja... ein Schritt, den ich regelmäßig vergesse: Vor dem Programmieren
einen Schritt weg vom Monitor machen und auf einem Blatt Papier
kritzeln...
> uint8_t counter;>> uint8_t tmp = counter & 0xaa;> counter = tmp & counter<<1 | tmp>>1 & ~counter;>> Irgendwie habe ich das Gefühl, dass man das noch weiter vereinfachen> kann, evtl. unter Verwendung der XOR-Operationen, komme aber nicht> drauf.
das hilft mir schon mal sehr weiter!
Danke und Gruß!
Andreas R. schrieb:> Wenn Du die Zähler gemeinsam dekrementierst, besser nur einen> Zähler> nehmen und 4x verwenden? ;-)
es sind halt unabhängige Zähler, die zwar gleichzeitig runtergezählt
werden aber zu anderen Zeiten gesetzt werden sollen.
Danke erstmal für die Hilfe, ich werde doch nur 2 4bit Zähler nutzen und
nicht 4 2bit Zähler. Versuche das gerade entsprechend anzupassen!
Gruß,
c-anfaenger schrieb:> ich werde doch nur 2 4bit Zähler nutzen und nicht 4 2bit Zähler.
Und warum? Hier RAM zu sparen bleibt blödsinn., Zumindest in 99.9%.
Weiter Idee zur Knobelaufgabe: wirklich subtrahiren.
Peter D. schrieb:> Das würde mich auch mal interessieren, was die Anwendung ist.
Vielleicht so etwas Ähnliches wie die vertical Counters in deiner
Entprellroutine? Nur dass die Counters hier horizontal sind, nur 1 statt
2 Bytes belegen und damit in der Anzahl auf 4 beschränkt sind.
ich habe inzwischen auch das herunterzählen hinbekommen, allerdings ist
das mir hier zu peinlich den mehrzeiligen Code zu posten ;)
Also die Anwendung ist folgender:
Eine Art Event-System:
Es werden verschiedene Events ausgelöst und dabei jeweils ein Bit von 0
auf 1 gekippt. Diese sollen nach kurzer Zeit wieder zurückgesetzt
werden.
Da die Events zu unterschiedlichen Zeitpunkten ausgelöst werden, hat
jedes Event einen eigenen Counter für das Zurücksetzen.
Das ganze findet in einer Smarthome-Bus Steuerung Anwendung, bei der ich
einige Events haben möchte, da einfach für alles 8bit zu nehmen würde
viel mehr Speicher fressen als notwendig.
gruß
c-anfaenger schrieb:> ich habe inzwischen auch das herunterzählen hinbekommen, allerdings ist> das mir hier zu peinlich den mehrzeiligen Code zu posten ;)
und warum nicht straight, mit Bitfeldern?
1
if(counter[n].A){counter[n].A--;}
> ds einfach für alles 8bit zu nehmen würde> viel mehr Speicher fressen als notwendig.
Das ist klar. Das ist aber normalerweise nicht die Frage. Es macht
regelmäßig nur dann Sinn, den Code zu verunstalten, wenn es konkret an
RAM mangelt. Denn hier hat Peter einfach Recht:
Peter D. schrieb:> Wenn der MC dafür zu knapp an RAM ist, dann ist er auch zu knapp an> Flash, um bei jeder Operation aufwendige AND/OR/Schiebe-Orgien> auszuführen.
Und wenn RAM wirklich knapp sein sollte, dann sind Arrays von 2-4 Bit in
einem Byte meist zweitbeste Lösung. Wenn es z.B. zu jedem Event-Timer
noch 2-3 Bits gibt (z.B. enable, prio, ...), dann lieber diese in einem
Byte gruppieren, um sie geschlossen und konsistent beackern zu können.
ich werde einen Atmega1284 nehmen, der hat ja 16KB SRAM.
Ich hatte überlegt alle Einstellungen um Events zu erkennen (z.B. auf
dem genutzten RS485 Bus sendet 0x12345678 den Befehl 0x01 mit Wert 0x04,
dann setze das Event-Bit auf 1 für Zeit 0x08) im RAM vorzuhalten um
nicht permanent das EPROM abzufragen.
Somit sind durch die Settings schon ein paar KB RAM belegt.