Hallo,
ich komme mit dem Tutorial nicht ganz zurecht.
Ich habe einen 2 dimensionalen Array, den ich gerne im Flash ablegen
würde:
1
constuint16_t2dArray[dim1][dim2]={{0},{0}};
Wenn ich jetzt in meinem Programm mir eine Zeile des Arrays z.B. 2dArry
[0] [von 0 bis 100] (Annahme Vorbelegung ungleich 0 wie hier) auslesen
möchte, wie mache ich das?
Das Auslesen soll z.B. einfach in einen eindimensionalen Array erfolgen:
Daniel schrieb:> Hallo,>> ich komme mit dem Tutorial nicht ganz zurecht.> Ich habe einen 2 dimensionalen Array, den ich gerne im Flash ablegen> würde:> const uint16_t 2dArray [dim1] [dim2] = { {0},{0}};>> Wenn ich jetzt in meinem Programm mir eine Zeile des Arrays z.B. 2dArry> [0] [von 0 bis 100] (Annahme Vorbelegung ungleich 0 wie hier) auslesen> möchte, wie mache ich das?
Als erstes wählst du einen gültigen C-Identifier und als zweitest legst
du die Daten ins Flash:
Martin Wende schrieb:> const char* EINSER[9] PROGMEM = { ... };> Oder wo is das problem?
Das ist kein 2-dimensionales Array, sondern ein 1-dimensionales
Pointer-Array.
Ich weiß nicht, ob ich ganz verstanden wurde, daher versuche ich es
nochmal an einem Beispiel.
Angenommen mein Array2D hat im Prinzip 5 Arrays à 20 Stellen, also
dim1=5 und dim2=20.
Nun möchte ich vom 1. Array2D alle 20 Stellen in die Variable Array1D
einlesen, also Array2D [0] [Stelle 0 bis 20] in eine Variable Array1D
[20] mit ebenfalls 20 Stellen lesen. Funktioniert dies so:
Wie wäre es wenn Du es einfach versuchst?
Du kannst ja nicht Dein ganzes restliches Leben lang jedesmal Andere
fragen bevor Du einen Code eintippst und den Compiler startest.
Uns (oder viele von uns) ist das einfach zu viel.
Darüberhinaus wird das Indizieren in jedem C-Buch erklärt.
Falls Du hingegen ein spezifisches Problem hast, dann formuliere es
auch.
Aber frage nicht: Geht das so?
Hallo,
danke für die Antwort. Ich kann das Programm natürlich schreiben,
allerdings habe ich kein HyperTerminal oder LCD, welches mir den Inhalt
der Variablen anzeigt bzw. ich so die Richtigkeit prüfen kann.
Das Programm oben kann ich durch den Compiler jagen, schon, aber das
sagt mir noch nichts aus, ob tatsächlich in den Variablen das ankommt,
was soll.
Nun nochmal Compiler freundlich:
> allerdings habe ich kein HyperTerminal oder LCD, welches mir den Inhalt> der Variablen anzeigt bzw. ich so die Richtigkeit prüfen kann.
Ne UART-USB Bridge gehört echt zur Minimalausrüstung, ohne die geht gar
nix. Investier ein paar $$$ dafür, das erleichtert dir das Hobby
ungemein!
Daniel schrieb:> Das Programm oben kann ich durch den Compiler jagen, schon, aber das> sagt mir noch nichts aus, ob tatsächlich in den Variablen das ankommt,> was soll.
Und - AFAIK - im avr-studio ist ein Simulator enthalten. Einfache Sachen
wie dein Programm kannst du damit sicher mal durchspielen.
In dem Fall ist dann nachdenken angesagt.
Angenommen, da wäre kein Flash im Spiel und du hättest ganz normale
Arrayzugriffe.
Wie löst du dann deine Aufgabenstellung?
Du würdest wohl sowas hier schreiben
1
uint16_tArray2D[dim1][dim2]={{0},{0}};
2
uint16_tArray1D[dim2]={0};
3
4
...
5
6
for(uint8_ti=0;i<dim2;i++){
7
Array1D[i]=Array2D[0][i];
8
}
Es ist leicht zu sehen, dass das genau das macht, was du vorhast. Oder?
So. Jetzt legst du Array2D ins Flash.
Als Folge davon kannst du nicht einfach mehr durch Angabe von
Array2D[0][i] auf einen Wert zugreifen. Warum ist das so? Weil so ein
Zugriff als Zugriff auf das SRAM aufgefasst werden würde und dort sind
nun mal die Daten nicht. Ausnahmslos jeder Zugriff auf derartige Werte
im Flash muss über eine Spezialfunktion gehen, der man die
Speicheradresse angibt, von der man den Wert haben will. (Oder eben, wie
Johann weiter oben schon geschrieben hat, man benutzt die Möglichkeiten
der neueren gcc Versionen, die einem diese Arbeit abnehmen).
Array2D[0][i] kann man ja auch auffassen als *&Array2D[0][i]. Dh. als
x x ist irgendein Symbol. Es steht für etwas, zb eine Variable
& x nimm die Adresse von diesem x (was immer auch x ist)
* & x und liefere den Wert an dieser Adresse
(vulgo: dereferenziere den Pointer)
Das ist genau das, was ja letztendes passiert, wenn du
i = x;
schreibst. An i wird der Wert zugewiesen, der sich ergibt, wenn man an
der Speicheradresse von x im Speicher nachsieht. Im eigentlichen Sinn
(wenn man alle Operationen ausschreibt), dann hat man da ja geschrieben
i = * & x;
(genau genommen steht da eigentlich:
* & i = * & x;
denn auch i ist ja erst mal nur ein Symbol, welches für etwas steht, zb
eine Variable. Daraus folgt aber auch, dass der * genau genommen für
verschiedene Operationen steht, je nachdem ob er links oder rechts vom =
auftaucht.
links vom = Speichere einen Wert unter der angegebenen Adresse
rechts vom = Liefere einen Wert von der angegebenen Adresse
Wir fassen aber beide 'Operationen' unter dem gemeinsamen Begriff
"Dereferenzieren" zusammen, weil aus dem Zusammenhang immer implizit
klar ist, welche der beiden möglichen Bedeutungen gemeint ist.
)
(und aus naheliegenden Gründen assoziiert der Compiler automatisch diese
Operationskette, wenn du i = x; schreibst)
Anstatt dem Dereferenzierungs-* tritt dann eben im Falle eines Zugriffs
im Flash die Spezialfunktion, die weiß, wie man auf das Flash korrekt
zugreift, wenn man die Speicheradresse hat.
Also wird ganz einfach der * durch die entsprechende pgm_read_...
Funktion ersetzt. Bei dir eben pgm_read_word, weil du weißt, dass du
einen 16 Bit Wert haben willst. Aus
* & x fürs SRAM
wird also
pgm_read_word( & x ); fürs Flash
x ist bei dir Array2D[0][i], also muss der Zugriff lauten
pgm_read_word( & Array2D[0][i] );
Oder dann eben 'im ganzen Satz' (inklusive Verschieben des Arrays ins
Flash)
Das alles ist völlig logisch, wenn man verstanden hat, was man da
eigentlich tut und warum man es tut und ein ganz klein wenig darüber
nachdenkt, wie Programmiersprachen eigentlich funktionieren.
Karl Heinz Buchegger schrieb:> for (uint8_t i=0; i<dim2; i++){> Array1D [i] = Array2D[0][i];> }
Sowas?
> #include <string.h>> memcpy (Array1D, Array2D[0], sizeof (Array1D));
und im Flash:
> #include <avr/pgmspace.h>> memcpy_P (Array1D, Array2D[0], sizeof (Array1D));
Vorsuaasetzung ist natürlich, daß Array1D ein Array ist und nicht nur
ein Zeiger. In letzerem Fall ist die Längenberechnung (sizeof)
anzupassen.