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. schrieb: > Ich braeuchte fuer den AVR eine 128 Bit grosse unsigned integer > Variable. Gibt es so etwas? Nicht als Basisdatentyp im Compiler.
@ 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.
G Ast schrieb: >>Ach ja: Lies mal was über Netiquette. > Was hat er denn falsch gemacht? Netiquette: Klare Beschreibung des Problems Speziell der erste Punkt.
[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)
Was für ein AVR ist das eigentlich? Gibt's einen besonderen Grund, dass du nicht das Hardware-SPI benutzen kannst?
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
1 | while (shift[counter] != 0) { |
2 | if (shift[counter] % 2) { |
3 | /* shiftmeout even, dividable by 2. Also see
|
4 | * http://de.wikipedia.org/wiki/Division_mit_Rest#Programmierung */
|
5 | shift1in(); |
6 | }
|
7 | |
8 | else { |
9 | shift0in(); |
10 | }
|
11 | shift[counter]=shift[counter]/2; |
12 | }
|
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
1 | inline void shift1in (void) { |
2 | SERPORT = (1<< SER); |
3 | SCKPORT = (1<< SCK); |
4 | }
|
5 | |
6 | inline void shift0in (void) { |
7 | SERPORT = (1>> SER); |
8 | SCKPORT = (1<< SCK); |
9 | }
|
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:
1 | uint8_t data[11]; |
2 | |
3 | void
|
4 | update_595_chain(void) |
5 | {
|
6 | uint8_t i; |
7 | uint8_t *dp; |
8 | |
9 | for (i = 0, dp = data; |
10 | i < 11; |
11 | i++, dp++) { |
12 | SPDR = *dp; |
13 | loop_until_bit_is_set(SPSR, SPIF); |
14 | }
|
15 | PORTB |= (1 << RCK); |
16 | PORTB &= ~(1 << RCK); |
17 | }
|
Ungetestet natürlich, nur ein kurzer Vorschlag.
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 >
1 | > while (shift[counter] != 0) { |
2 | > if (shift[counter] % 2) { |
3 | > /* shiftmeout even, dividable by 2. Also see |
4 | > * http://de.wikipedia.org/wiki/Division_mit_Rest#Programmierung
|
5 | > */
|
6 | > shift1in(); |
7 | > } |
8 | >
|
9 | > else { |
10 | > shift0in(); |
11 | > } |
12 | > shift[counter]=shift[counter]/2; |
13 | > } |
14 | >
|
> > 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.
1 | inline void shiftarrayin (void) { |
2 | |
3 | for (uint8_t counter=0; counter<(SHIFTBITS/8); counter++) { |
4 | uint8_t byte = shift[counter); |
5 | |
6 | // die 8 Bits raustakten
|
7 | for( uint8_t i = 0; i < 8; ++i ) { |
8 | if( byte & 0x01 ) |
9 | SERPORT |= (1<< SER); |
10 | else
|
11 | SERPORT &= ~(1<< SER); |
12 | |
13 | // 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.