Hallo
Hab ein Problem mit einem Pointer auf ein Array im Flash und bitte um
Hilfe/Aufklährung warum es nicht klappt.
Ich versuche zu verstehen wie Pointer angewendet werden indem ich ein
Menü ausgebe welches sich in einem Array befindet das durch einen
Pointer aufgerufen wird.
Warum funktioniert dieser teil:
1
write_str_p(MENU[0],5,10,WHT,RED);
2
write_str_p(MENU[1],5,18,WHT,RED);
3
write_str_p(MENU[2],5,26,WHT,RED);
und dieser teil nicht:
1
for(inti=0,j=0;i<sizeof(MENU)/sizeof(*MENU);i++)
2
{
3
write_str_p(MENU[i],5,j+=10,WHT,RED);
4
}
hier erscheinen auf dem Display irgendwelche zeichen auf der gesamten
zeile und das drei mal hintereinander
Im Anhang sind die source Dateien zu finden.
MfG
Hi
kannst du bitte mal den kompletten Code posten, speziell den Teil an dem
das Menü initialisiert wird.
Und bitte mal schaun, was bei sizeof(MENU)/sizeof(*MENU) herauskommt.
Thomas
nicht funktioniert haben :-)
Du hast 2 Dinge die im Flash liegen.
sowohl MENU als auch die Pointer die in MENU gespeichert sind, liegen im
Flash.
Um also den Pointer auf den Text zu bekommen, musst du schon einmal aus
dem Flash lesen. Und das tust du nicht.
PS:
In C hat man die Konvention, dass Namen die ausschliesslich in
Grossbuchstaben geschrieben sind, immer ein Makro kennzeichnen. Es gibt
keinen Grund von dieser Konvention abzuweichen, zumal das eine der
wenigen Konventionen ist, die tatsächlich von so gut wie allen
C-Programmierern eingehalten wird.
MO schrieb:> Wird ja auf den Flash zugegriffen.
Nochmal:
Du hast eine 2 stufige Datenstruktur die komplett im Flash liegt.
>> Das hier z.B. geht und es wird 3 mal Farben untereinander angezeigt.>
1
>for(inti=0,j=0;i<sizeof(MENU)/sizeof(*MENU);i++)
2
>{
3
>write_str_p(MENU[0],5,j+=10,WHT,RED);
4
>}
5
>
6
>
das kann nicht funktionieren. Höchstens zufällig. Oder aber du hast das
zu einem Zeitpunkt getestet, als deine Datenstruktur noch so aussah
1
constchar*MENU[]={txt1,txt2,txt3};
Jetzt liegt MENU nicht im Flash und du kannst den i-ten Pointer mittels
MENU[i] bekommen.
Deine Struktur sieht aber so aus
1
constchartxt1[]PROGMEM="Farben";
2
constchartxt2[]PROGMEM="Contrast";
3
constchartxt3[]PROGMEM="Helligkeit";
4
5
constchar*MENU[]PROGMEM={txt1,txt2,txt3};
sowohl das Array "MENU" als auch die Texte liegen im Flash:
1
MENU
2
+---------+
3
| o--------------------> "Farben"
4
+---------+
5
| o--------------------------> "Contrast"
6
+---------+
7
| o----------> "Helligkeit"
8
+---------+
Um also an die Pointer zu kommen, die du dann an write_str_p übergeben
kannst, musst du sie aus MENU auslesen. Da aber MENU selbst auch im
Flash liegt, musst du die Flash Funktionen benutzen um an diesen Pointer
zu gelangen.
>> Das Problem liegt irgendwie in der incrementierung von i!?
Ganz sicher nicht.
Ich verstehe jetzt nur Bahnhof.
Mit diesem Code steht auf den Display 3mal untereinander "Contrast".
1
intmain(void)
2
{
3
mcu_init();
4
disp_init();
5
6
for(inti=0,j=0;i<sizeof(MENU)/sizeof(*MENU);i++)
7
{
8
write_str_p(MENU[1],5,j+=10,WHT,RED);
9
}
10
11
while(1);
12
13
return0;
14
}
Ich gebe doch der Function "write_str_p" die Adresse des Eintrages in
der 2ten zeile(quasi txt2 also "Contrast") dessen Adresse im Pointer
"MENU[1]" steht.
und hiermit:
>> while (((c = pgm_read_byte(p++))!=0))
greife ich doch auf dem Flash zu!?
was auch klappt.
!!!ABER!!!
Benutze ich statt der 1 das i also "MENU[i]" um in der Schleife alle 3
einträge auszugeben, liest/zeigt der µC andere zeichen an.
MO schrieb:> Ich verstehe jetzt nur Bahnhof.
Machs einfach so, wie ich es dir gezeigt habe
> Ich gebe doch der Function "write_str_p" die Adresse des Eintrages in> der 2ten zeile(quasi txt2 also "Contrast") dessen Adresse im Pointer> "MENU[1]" steht.
Ja.
Aber wo hast du den denn her?
Der richtige steht doch selber wieder im Flash!
Dein MENU Array steht im Flash!
Wenn du von dort etwas auslesen willst (zb einen Pointer), dann musst du
dafür die Flash Funktionen benutzen. Was du dann mit dem Pointer weiter
machst, steht hier nicht zur Debatte. Um von MENU zu lesen musst du über
die Flash Funktionen gehen. Das ist so, weil du hier
1
constchar*MENU[]PROGMEM={txt1,txt2,txt3};
das MENU Array als ganzes ins Flash verfrachtet hast. Da gehts noch
nicht mal darum, was denn im MENU Array enthalten ist. Und wenn das
einfach nur ein paar Zahlen wären: Um von MENU etwas zu lesen, musst du
die Flash Funktionen benutzen.
> und hiermit:>>>> while (((c = pgm_read_byte(p++))!=0))>> greife ich doch auf dem Flash zu!?
Das ist uninteressant. die Funktion ist schon ok.
Du hast ganz einfach nicht den richtigen Pointer
MO schrieb:> Hab das jetzt so in der .h Datei und es klapp nun auch in der Schleife.>>
1
>//STRINGS IN FLASH
2
>constchartxt1[]PROGMEM="Farben";
3
>constchartxt2[]PROGMEM="Contrast";
4
>constchartxt3[]PROGMEM="Helligkeit";
5
>
6
>constchar*ptrMENU[]={txt1,txt2,txt3};
7
>
>
Jetzt hast du das ptrMENU Array aus dem Flash rausgenommen.
Klar klappt nun ein Zugriff mittels ptrMENU[i]
(Aber eigentlich hast du geschummelt und bist deinem Verständnisproblem
ausgewichen :-)
BÖSER JUNGE ;)
Was ich verstanden hab ist, dass ich mit
>>char *ptrMENU[] PROGMEN = { txt1,txt2,txt3};
auf dem Flash zugreife was mir auch klar war und ich nur mit
>>pgm_read_byte(ptr) bzw. pgm_read_word(ptr)
Daten aus dem Flash holen kann auch klar.
Was mich aber stutig gemacht hat ist, warum es hier mit geht (das ging
wirklich)
> write_str_p(MENU[0], 5, 10, WHT, RED);> write_str_p(MENU[1], 5, 18, WHT, RED);> write_str_p(MENU[2], 5, 26, WHT, RED);
aber nicht hiermit
> for(int i=0,j=0;i<sizeof(ptrMENU)/sizeof(*ptrMENU);i++)> {> write_str_p(ptrMENU[i], 5, j+=10, WHT, RED);> }
Danke euch für die Hilfe.
MfG
MO schrieb:> Was mich aber stutig gemacht hat ist, warum es hier mit geht (das ging> wirklich)
Daran hab ich auch nicht mehr gedacht. A.K. hatte die Lösung. Das
funktionierte wegen "works by Optimization". Hättest du den Optimizer
abgeschaltet, hätte es ebenfalls nicht mehr funktioniert.
Der Compiler kennt ja den Wert von MENU[0]. Er hat ihn ja vorher
gesehen. Also hat er ganz einfach für dich mitgedacht und anstelle eines
Zugriffs auf MENU[0] gleich den richtigen Wert in den Code eingesetzt.
Drum hat das funktioniert.
Also Zufall. Wenn der Compiler den Arrayinhalt vorher nicht gesehen
hätte, hätte auch der Optimizer das nicht irrtümlich hinbiegen können.
MO schrieb:> Verzeit mir das doppelposting>> Geht das was ich vorhab auch eleganter und/oder schöner?
So wie ich es dir weiter oben gezeigt habe. Dann liegt alles im Flash.
Man könnte das höchstens noch zusammenfassen:
ob as allerdings eleganter bzw. schöner ist, darüber kann man trefflich
diskutieren.
Was aber wahrscheinlich nicht so bleiben wird, ist die Verwendung der
sizeof zur Bestimmung der Arraygröße. Im Endeffekt wirst du ja eine
einzige Routine haben, die verschiedene Menüs ausgeben kann, jedes mit
seiner eigenen Größe.
Ausserdem hast du ja noch keine Funktionalität an deine 'Menuüs'
gekoppelt, so dass du demnächst wahrscheinlich sowieso dieses
PointerArray wieder auflösen und durch Strukturen ersetzen wirst.