Hallo,
Ich braeuchte fuer den AVR eine 128 Bit grosse unsigned integer
Variable. Gibt es so etwas?
Habe schon inttypes.h und stdint.h durchforstet, hier komme ich bis auf
uint64_t :/
Programmiert wird in C mit avr-libc 1.6.8, avr-binutils 2.20.1 und
avr-gcc 4.5.0
@ Armin S. (nimra)
>Ich braeuchte fuer den AVR eine 128 Bit grosse unsigned integer>Variable. Gibt es so etwas?
Willst du das Vermögen von Dagobert Duck zählen? ;-)
Sowas macht man auf einem so kleinen Prozessor wohl besser als 16 Byte
Array.
MfG
Falk
Falk Brunner schrieb:> Willst du das Vermögen von Dagobert Duck zählen? ;-)
Ich habe 11 74HC595 Schieberegister kaskadiert (also ein
88Bit-Schieberegister) und wollte die jeweils aktuellen Zustaende
bitweise speichern. (Ja, ein AVR mit mehr Pins waere auch gegangen,
allerdings mag ich kein SMD).
Hatte mir dazu schon alle Funktionen geschrieben und wollte mein
Programm jetzt einfach von 16 auf 128 bit erweitern. Dann aber die
Enttaeuschung, uintXXX_t gibt es nur bis 64 Bit :/ .
Mal schauen, entweder ich mache das ganze jetzt mit einem Array (wird
die einfachste Loesung sein) oder Arbitrary Precision Arithmetic
(http://en.wikipedia.org/wiki/Bignum)
NIMRA
Armin S. schrieb:> Ich habe 11 74HC595 Schieberegister kaskadiert (also ein> 88Bit-Schieberegister) und wollte die jeweils aktuellen Zustaende> bitweise speichern.
Und dafür
> Arbitrary Precision Arithmetic
Hilfe!!!!
@ Armin S. (nimra)
>Ich habe 11 74HC595 Schieberegister kaskadiert (also ein>88Bit-Schieberegister) und wollte die jeweils aktuellen Zustaende>bitweise speichern.
Warum habe ich das geahnt, dass eine 128 Bit Zahl keine Sekunde benötigt
wird? ;-)
>Hatte mir dazu schon alle Funktionen geschrieben und wollte mein>Programm jetzt einfach von 16 auf 128 bit erweitern. Dann aber die>Enttaeuschung, uintXXX_t gibt es nur bis 64 Bit :/ .
Und selbst die sind auf dem AVR schweinelangsam :-(
>Mal schauen, entweder ich mache das ganze jetzt mit einem Array (wird>die einfachste Loesung sein)
Das ist es. Eine Funktion vom Typ "Setze Bit X im Array" ist in 10 min
programmiert. Siehe auch die Links im Artikel Bitmanipulation.
> oder Arbitrary Precision Arithmetic>(http://en.wikipedia.org/wiki/Bignum)
NEIN!!!
MfG
Falk
Ach ja: Lies mal was über Netiquette.
[Netiquette]
Ach geh seiz doch nicht so. Der TO ist immerhin schon beim zweiten
Posting mit dem eigentlichen Problem rausgerückt, das halte ich durchaus
für vertretbar. Und der Rest vom Posting war vorbildlich ('braucht x',
'habe an der Quelle gesucht', 'geht nur bis y', 'verwende z in exakter
Versionsnummer..'). Wenn alle Frederöffnungen so klar wären könnte man
mindestens die Hälfte aller Antworten einsparen.
Also Armin, lass Dir nicht drausbringen. Nimm ein (uint8_t-)Array mit
zwei oder drei 'Interface'funktionen und gut iss.
@ g457 (Gast)
>[Netiquette]>Ach geh seiz doch nicht so. Der TO ist immerhin schon beim zweiten>Posting mit dem eigentlichen Problem rausgerückt, das halte ich durchaus>für vertretbar.
Wenn gleich das für "lokale Verhältnisse" noch recht schnell war, soll
doch der OP auch was lernen, nicht nur übers Bitschieben. Deshalb der
Hinweis.
Wo ist das Problem?
Ich hab ja nicht geschrieben "Lies verdammt nochmal was über Netiquette
du Depp!". ;-)
MfG
Falk
Ich gelobe Besserung :D
Habe das ganze jetzt mal mit einem Array aus 11 uint8_t versucht(auch
wenn mir Falk oben zu einem Array aus 16 Byte geraten hat, war wohl 16
Bit gemeint). Testen kann ich das ganze erst morgen, koentet ihr evtl.
trotzdem schon mal einen Blick darueber werfen ob das so funktioniert?
Danke fuer die Hilfe die ich bis jetzt erhalten habe und erhalten werde.
Ich bin einfach noch nicht ganz so vertraut mit der Materie.
NIMRA
Armin S. schrieb:> Ich gelobe Besserung :D>> Habe das ganze jetzt mal mit einem Array aus 11 uint8_t versucht(auch> wenn mir Falk oben zu einem Array aus 16 Byte geraten hat, war wohl 16> Bit gemeint).
Nö.
Waren schon 16
Du sagtest, du bräuchtest 128 Bit. Ein Byte hat 8 Bit. 128 / 8 -> 16
Armin S. schrieb:> Bit gemeint). Testen kann ich das ganze erst morgen, koentet ihr evtl.> trotzdem schon mal einen Blick darueber werfen ob das so funktioniert?
Das erscheint mir ziemlicher Unsinn zu sein.
Schreib dir doch erst mal 2 Funktionen
void SetBit( uint8_t BitNr );
void ClearBit( uint8_t BitNr );
welche, analog zu
variable |= ( 1 << BitNr );
bzw variable &= ~( 1 << BitNr );
ein bestimmtes Bit in deinen 'virtuellen 88 Bit' setzt, bzw. löscht.
Und das raustakten an den 595 kann ja nicht das Problem sein, wenn du 1
Byte raustakten kannst. Einfach alle 11 Bytes nacheinander raustakten
und einen RCK nachschieben.
(Und nein, so wie du das mit der while Schleife vor hast, kann man das
nicht machen. Du musst schon alle Bits bearbeiten, auch wenn in der
entsprechenden Variable keines auf 1 gesetzt ist und die Variable daher
0 ist)
Karl heinz Buchegger schrieb:> Armin S. schrieb:>> Ich gelobe Besserung :D>>>> Habe das ganze jetzt mal mit einem Array aus 11 uint8_t versucht(auch>> wenn mir Falk oben zu einem Array aus 16 Byte geraten hat, war wohl 16>> Bit gemeint).>> Nö.> Waren schon 16>> Du sagtest, du bräuchtest 128 Bit. Ein Byte hat 8 Bit. 128 / 8 -> 16
Dass 16 Byte auf den meisten Systemen (nicht immer!) 128 Bit sind ist
mir schon klar. Aber lies die ersten 3 Postings nochmal durch, da machen
16 Byte keinen Sinn.
In der Hoffnung mich nicht schon wieder total blamiert zu haben,
NIMRA
Armin S. schrieb:>> Dass 16 Byte auf den meisten Systemen (nicht immer!) 128 Bit sind ist> mir schon klar. Aber lies die ersten 3 Postings nochmal durch, da machen> 16 Byte keinen Sinn.
Wenn du von Anfang an gesagt hättest, dass du nur 88 Bits benötigst,
hätte Falk auch korrekt ausgerechnet, dass du nur 11 Bytes dazu
brauchst.
Das hast du aber nicht!
Du hast gesagt, du benötigst einen Datentyp mit 128 Bits. Und daher hat
Falk messerscharf dafür ausgerechnet, dass man dazu 16 Bytes benötigt.
Deine Information, das du nur 88 Bits (für 11 Stück 595) benötigst, ist
erst nach dieser Falkschen Rechnerei gekommen. Du magst vielleicht auch
noch mal die ersten 3 Postings durchsehen: Die einzige Zahl die dort
auftaucht, sind 128 Bit.
Fazit: Schreib immer gleich was das ursprüngliche Problem ist, anstatt
nach einer Problemlösung zu fragen von der du glaubst, dass sie dein
Problem lösen könnte.
Ich habe hier einen Mega16. Hardware SPI schien mir komplizierter zu
sein als alles in Software zu machen, und eine hohe Geschwindigkeit
brauche ich auch nicht, daher erst mal in Software.
Karl heinz Buchegger schrieb:
>Und das raustakten an den 595 kann ja nicht das Problem sein, wenn du 1>Byte raustakten kannst. Einfach alle 11 Bytes nacheinander raustakten>und einen RCK nachschieben.
Genau das mache ich doch schon.
Schau mal in die Funktion shiftarrayin
NIMRA
P.S. Ich finde es richtig super von euch dass ihr versucht mir zu
helfen. Vielen Dank dafuer!
Armin S. schrieb:>>Byte raustakten kannst. Einfach alle 11 Bytes nacheinander raustakten>>und einen RCK nachschieben.> Genau das mache ich doch schon.
Nö.
Das machst du nicht
> Schau mal in die Funktion shiftarrayin
Das hier
taktet keine 8 Bit raus, sondern eine zunächst unbekannte Anzahl an
Bits, je nach Inhalt von shift[counter]. Ist shift[counter] zb von vorne
herein schon 0, dann wird gar nichts rausgetaktet.
Ausserdem ist es wohl nicht so schlau, wenn deine interne
Repräsentierung alleine durch das Raustakten an die 595 zerstört wird.
Das macht weitergehende Abfragen über den aktuell an einem spezifischen
595-Pin anliegenden Zustand nicht besonders einfach. Solange man die
nicht weiter braucht, gehts ja noch. Aber wehe, man möchte die
irgendwann einmal tatsächlich nach dem Raustakten weiterverwenden.
Okay ich hab das falsch verstanden, ich bitte vielmals um
Entschuldigung.
Ich dachte Falk meint ein Array aus mehreren 16 Byte Variablen, darum
habe ich gedacht er meint 16 Bit.
Hier ist die Gesamtgroesse des Arrays gemeint.
NIMRA
Das erscheint ebefalls ziemlicher Nonsense zu sein.
Du möchtest dir im AVR Studio noch einmal den Abschnitt über Bit setzen
und Bit löschen an einem Port ansehen. Gefragt sind hier die
Schreibweisen, die nur 1 bestimmtes Bit verändern und nicht
rundumschlagmässig den komlpetten Port beschreiben.
Karl heinz Buchegger schrieb:> Das erscheint ebefalls ziemlicher Nonsense zu sein.
Ich nehms zurück.
Wenn du sonst nichts an dem Port angeschlossen hast, mags gehen. Schlau
ist es IMHO trotzdem nicht, hier zu sehr zu künsteln.
Armin S. schrieb:> Hardware SPI schien mir komplizierter zu> sein als alles in Software zu machen
Nö, ist viel einfacher. Du musst nur 11 mal das Register SPDR
beschreiben und anschließend drauf warten, bis das SPIF-Bit wieder
gesetzt worden ist. Nach allen 11 Bytes ziehst du einmal aim Bit
für das parallel Laden der Ausgangsregister und setzt es gleich
wieder zurück -- finito!
Pseudocode:
Jörg Wunsch schrieb:> Armin S. schrieb:>> Hardware SPI schien mir komplizierter zu>> sein als alles in Software zu machen>> Nö, ist viel einfacher.
Nicht vergessen: Den SS Pin auf Ausgang konfigurieren.
Sinnigerweise könnte man den gleich für RCK benutzen.
Karl heinz Buchegger schrieb:> Armin S. schrieb:>>>>Byte raustakten kannst. Einfach alle 11 Bytes nacheinander raustakten>>>und einen RCK nachschieben.>> Genau das mache ich doch schon.>> Nö.> Das machst du nicht>>> Schau mal in die Funktion shiftarrayin>> Das hier>
>> taktet keine 8 Bit raus, sondern eine zunächst unbekannte Anzahl an> Bits, je nach Inhalt von shift[counter]. Ist shift[counter] zb von vorne> herein schon 0, dann wird gar nichts rausgetaktet.> Ausserdem ist es wohl nicht so schlau, wenn deine interne> Repräsentierung alleine durch das Raustakten an die 595 zerstört wird.> Das macht weitergehende Abfragen über den aktuell an einem spezifischen> 595-Pin anliegenden Zustand nicht besonders einfach. Solange man die> nicht weiter braucht, gehts ja noch. Aber wehe, man möchte die> irgendwann einmal tatsächlich nach dem Raustakten weiterverwenden.
Du hast recht, das ist mir gar nicht aufgefallen, Danke! Die Funktion
war schon dafuer gedacht alle Bits rauszutakten, ich habe nur die
Programmierung versaut.
Ich schreib das ganze nochmal neu, die shift0in und shift1in werde ich
auch nochmal ueberarbeiten. Danke an dieser Stelle fuer den Code von J.
Wunsch. SS als Ausgang ist klar, habe gelesen, dass es andernfalls
teilweise unerwuenschte Nebeneffekte gibt. Muss dazu aber auch nochmal
den Abschnitt im Datenblatt nachlesen.
Aus dem ganzen soll spaeter einmal ein 9x9x9 LED Cube werden, die
einzelnen Ebenen werden gemultiplext. JP1 ist eine 3,5mm Klinkenbuchse,
ein Audioeingang. Die an ADC0 ankommenden Signale sollen dann die
angezeigten Animationen beeinflussen, Stichwort Fast Fourier
Transformation, auch FFT
Im Anhang noch der "Schaltplan" (mehr als Skizze zum Bau fuer mich
selbst als ein richtiger Schaltplan) fuer den LED Cube der mal daraus
werden soll.
Jetzt wisst ihr welches "Monster" ich bauen will und warum die 11
Schieberegister.
Danke fuer eure Geduld mit mir.
NIMRA
Armin S. schrieb:> Ich schreib das ganze nochmal neu, die shift0in und shift1in werde ich> auch nochmal ueberarbeiten.
Ich bin zwar ein Freund von Einzelfunktionen. Man kann es aber auch
übertreiben. Im Grunde genommen braucht diese Funktionen kein Mensch.
Der Code wird durch diese Funktionen nicht klarer.
// Nachdem die Datenleitung richtig steht, einen SCK Puls
14
// geben. Zwischen dem Setzen und dem Rücknehmen etwas warten
15
// Da byte sowieso um 1 Position geschoben werden muss, kann
16
// man diese Aktion auch gleich zum 'warten' hernehmen
17
SCKPORT|=(1<<SCK);
18
byte>>=1;
19
SCKPORT&=~(1<<SCK);
20
}
21
}
22
23
//
24
// Alle Bytes sind draussen: In die Latches übernehmen
25
//
26
RCKPORT|=(1<<RCK);
27
RCKPORT&=~(1<<RCK);
28
}
PS: Über Namen kann man zwar streiten, aber mich hat dein shiftarrayin
ehrlich gesagt verwirrt. Aus Sicht des µC werden die Daten zum 595
hinausgetaktet.
Es funktioniert!
Habe mich jetzt fuer die Variante von kbuchegg entschieden.Ich glaube
jetzt habe ich das ganze auch verstanden.
Man prueft mit einem binaeren & ob das unbedeutsamste Bit gesetzt ist.
Wenn ja schaltet man den Ausgang auf high, wenn nicht auf low. Jetzt
schiebt man die Bits alle um eine Stelle nach rechts, wodurch das
unbedeutsamste Bit wegfaellt. Das zweitunbedeutsamste wird nun zum
unbedeutsamsten, das drittunbedeutsamste zum zweitunbedeutsamsten usw.
Dann gibt man einen SCK puls aus, um dem Schieberegister zu
signalisieren, dass das naechste Bit kommt und das Schieberegister um
eine Stelle weiterschieben soll. Das ganze macht man dann 8 mal und man
hat sein Byte durch. Dann macht man weiter mit dem naechsten Byte aus
dem Array. Wenn man das Array durch hat gibt man noch einen RCK puls, um
das ganze auf die Ausgaenge zu geben.
Habe mal fuer ein paar Prozessoren testcompiliert (alle mit -Os):
ATTiny 13 84 Byte
ATTiny 2313 102 Byte
ATMega 8 106 Byte
ATMega 48/88 120 Byte
ATMega 16/32 158 Byte
ATMega 168 178 Byte
Das ganze ist auch noch erfreulich effizient :D, wenngleich ich mir die
grossen Unterschiede nicht erklaeren kann.
Danke an alle, mir geholfen haben, ganz besonders an kbuchegg.
NIMRA
@ Armin S. (nimra)
>Man prueft mit einem binaeren & ob das unbedeutsamste Bit gesetzt ist.
Das ist das niederwertigeste Bit oder neudeutsch least significant bit.
Oder Bit Nummer Null, auch als Bit #0 geschrieben.
>Das ganze ist auch noch erfreulich effizient :D, wenngleich ich mir die>grossen Unterschiede nicht erklaeren kann.
Das liegt daran, dass größere AVRs größere Interruptvektortabellen
haben.
Die werden immer vollstängig gespeichert, egal ob notwendig oder nicht.
MFG
Falk