Forum: Compiler & IDEs uint128_t mit AVR?


von Armin S. (nimra)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

Armin S. schrieb:

> Ich braeuchte fuer den AVR eine 128 Bit grosse unsigned integer
> Variable. Gibt es so etwas?

Nicht als Basisdatentyp im Compiler.

von Falk B. (falk)


Lesenswert?

@  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

von Armin S. (nimra)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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!!!!

von Falk B. (falk)


Lesenswert?

@  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.

von G Ast (Gast)


Lesenswert?

>Ach ja: Lies mal was über Netiquette.

Was hat er denn falsch gemacht?

von eklige Tunke (Gast)


Lesenswert?

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.

von g457 (Gast)


Lesenswert?

[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.

von Falk B. (falk)


Lesenswert?

@  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

von Armin S. (nimra)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was für ein AVR ist das eigentlich?  Gibt's einen besonderen Grund,
dass du nicht das Hardware-SPI benutzen kannst?

von Armin S. (nimra)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Armin S. (nimra)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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.

von Armin S. (nimra)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Armin S. (nimra)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Armin S. (nimra)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@  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
Noch kein Account? Hier anmelden.