Frank wrote:
> du meinst mit..
>
1 | > eeprom_read_block(&mybuffer,&struct_name_EE[i],sizeof(struct_Name));
|
2 | >
|
> das "normale" EEprom beschreiben und lesen klappt.
Gut.
> Ich check einfach
> nicht wie ich die Funktionen einbinden muss.
Na, zb hier
Hier legst du dir ein Array von 6 Pointer an, die auf Texte zeigen
können.
Und hier
1 | for( i = 0; i < 6; ++i )
|
2 | {Index[i] = struct_name_EE[i].filename;}
|
befüllst du dieses Array. Jeder einzelne der Index-Pointer zeigt auf
einen Text. Aber wo sind denn diese Texte? Die liegen doch nach wie vor
im EEPROM rum. Alles was du dir bisher gemacht hast, sind Verweise,
wobei jeder Verweis ins EEPROM zeigt.
Bis hierher ist alles gut
Jetzt kommt die Sortierung.
Du willst deine Verweise so umsortieren, dass man sortiert an die Texte
rankommt, wenn man nur die Verweise in der richtigen Reihenfolge
abarbeitet. Dazu genügt es, die Verweise umzuschaufeln. Auch diese Idee
ist ja an sich nicht schlecht.
Aus
Index
+--------------+ +---------------+
| o--------------------------->| "ABCD" |
+--------------+ +---------------+
| o--------------------------->| "XYZ" |
+--------------+ +---------------+
| o--------------------------->| "IJKL" |
+--------------+ +---------------+
| o--------------------------->| "EFGH" |
+--------------+ +---------------+
wird so
Index
+--------------+ +---------------+
| o--------------------------->| "ABCD" |
+--------------+ +---------------+
| o------------------+ +--->| "XYZ" |
+--------------+ +---|----+ +---------------+
| o--------------|---|-------->| "IJKL" |
+--------------+ | | +---------------+
| o--------------+ +-------->| "EFGH" |
+--------------+ +---------------+
Sucht man die Texte in der Reihenfolge auf, die über das Index Array
vorgegeben wird, so sind diese sortiert, ohne dass man die Texte
umsortieren musste.
Aber: Die Texte liegen nachwievor im EEPROM!
Wenn man an die eigentlichen Texte rann will, muss man die EEPROM
Funktionen benutzen um sie auszulesen. Die Sortierung von Index (welches
im SRAM) liegt, hat daran ja nichts geändert.
Daher kann hier
1 | int Compare( const void* Arg1, const void* Arg2 )
|
2 | {
|
3 | char* pString1 = *(char**) Arg1;
|
4 | char* pString2 = *(char**) Arg2;
|
5 |
|
6 | return strcmp( pString1, pString2 );
|
7 | }
|
der strcmp nicht funktionieren.
Sowohl pString1 als auch pString2 enthalten ja Adressen, die ins EEPROM
zeigen. Und damit kann strcmp nun mal nichts anfangen! Entweder du
schreibst dir selbst eine Vergleichsfunktion, die auf Einzelbyte Ebene,
analog zu strcmp, den Vergleich durchführt, oder du lädst dir zuerst die
Texte vom EEPROM in temporäre Variablen, die im SRAM liegen (also stink
normale char-Arrays) und lässt dann strcmp darauf los.
Selbiges hier
1 | for( i = 0; i < 6; ++i )
|
2 | {uart_puts(Index[i]);}
|
uart_puts erwartet die Texte, die es ausgeben soll im SRAM und nicht im
EEPROM.
> Muss ich den Umweg über einen Buffer gehen?
Das ist eine Möglichkeit. Aber letztendlich arbeiten alle
String-Funktionen irgendwann auf Einzelzeichen. uart_puts wird einen
String ausgeben, indem es jedes einzelne Zeichen über uart_putc ausgibt.
Zb so
(Ich schreibs jetzt absichtlich in langer Form)
1 | void uart_puts( const char* text )
|
2 | {
|
3 | char c;
|
4 |
|
5 | c = *text; // Zeichen holen
|
6 | while( c != '\0' ) { // war das schon das letzte Zeichen des Strings?
|
7 | uart_putc( c ); // Nein: Zeichen über uart_putc ausgeben
|
8 | text++; // Adresse zumnächsten Zeichen erhöhen
|
9 | c = *text; // und das Zeichen von dort holen
|
10 | }
|
11 | }
|
an 2 Stellen kommt
c = *text;
vor. Hier wird ein einzelner Character von einer Speicherstelle geholt.
Die Adresse von der gelesen werden soll, steht in text. Durch die Art
des Zugriffs (Dereferenzierung mit *) ist klar, dass die Adresse als
Adresse ins SRAM aufzufassen ist und daher wird auch aus dem SRAM
gelesen.
Aber: Deine Adresse ist keine SRAM Adresse! Deine Adresse ist eine
Adresse ins EEPROM. Daher musst du das Zeichen anders besorgen: mittels
der eeprom_read_byte Funktion.
Der Rest der Ausgabelogik bleibt gleich, lediglich die Art und Weise,
wie das auszugebende Zeichen besorgt wird ändert sich
1 | void uart_puts_eeprom( const char* text )
|
2 | {
|
3 | char c;
|
4 |
|
5 | c = eeprom_read_byte( text ); // Zeichen holen
|
6 | while( c != '\0' ) { // war das schon das letzte Zeichen des Strings?
|
7 | uart_putc( c ); // Nein: Zeichen über uart_putc ausgeben
|
8 | text++; // Adresse zumnächsten Zeichen erhöhen
|
9 | c = eeprom_read_byte( text ); // Zeichen holen
|
10 | }
|
11 | }
|
und schon hast du eine Funktion, die wie uart_puts funktioniert, nur
dass die übergebene Adresse nicht die Adresse eines Strings im SRAM,
sondern die Adresse eines Strings im EEPROM ist. Perfekt geeignet, um
hier
1 | for( i = 0; i < 6; ++i )
|
2 | uart_puts_eeprom( Index[i] );
|
eingesetzt zu werden, denn in Index stehen ja lauter Adressen von Texten
im EEPROM.
So jetzt bist du drann, dir einen Ersatz für die strcmp Funktion zu
schreiben, die als Argumente Adressen von Texten im EEPROM erhält.
Überleg dir einfach mal, wie wohl strcmp arbeiten wird. Das formulierst
du dann in C (und testest es!) und ersetzt danach alle Speicherzugriffe,
bei denen ein einzelnes Zeichen aus dem Speicher geholt werden muss
durch die entsprechenden Funktionsaufrufe, die das Zeichen aus dem
EEPROM anstatt aus dem SRAM holen.