Hallo zusammen, ich habe ein Problem mit meinem Menü. Ursprünglich war ein Menüpunkt in einer Structure gespeichert (Text als String, Funktion die aufgerufen wird, int der den aktiven Punkt indiziert) Um Platz im RAM zu sparen wollte ich die Strings die jeweils ausgegeben werden sollen in den Flashspeicher verlagern. Das hat auch soweit geklappt. Wenn ich zum Beispiel einen solchen String wieder ausgeben wollte konnte ich das mit char buffer[10]; for (unsigned char i = 0; i <4; i++) { strcpy_P(buffer, (PGM_P)pgm_read_word(&(MainMenu[i]))); LCD_STRING (buffer,0,i); } machen. Wenn ich nun allerdings versuche dieses Konstrukt in die Menupunkt Ausgabe zu integrieren kommt garnichts auf dem LCD an. Ich habe mal den gesamten SourceCode mit angehängt, wobei die relevanten Files wohl PrintMenu.c und MainMenu.c sind. Der Aufruf geschieht in Moodlight204112.c. Ich wäre sehr dankbar wenn mir jemand sagen könnte was ich falsch mache bzw falsch verstanden habe. Vielen Dank schonmal. Grüße Stefan
Hallo, Stefan Friedrich schrieb: > pgm_read_word(&(MainMenu[i])) wenn Du diese Frage beantworten kannst, bist Du ein Stück weiter: wie viele Bytes werden pro Aufruf gelesen ?
Danke schonmal für die schnelle Antwort. Also wenn ich das richtig verstanden hab wird hier nur die Adresse des Strings weitergegebn. Und gelesen wird hier ein Word also 2 Byte. Soviel ich weiß sollte das auch passen da die Adresse 16 Bit hat. Und wenn ich diese Funktion nutze funktioniert das auch. Also: char string_1[] PROGMEM = "Program"; char string_2[] PROGMEM = "Options"; char string_3[] PROGMEM = "Time"; char string_4[] PROGMEM = "Help"; PGM_P MainMen[] PROGMEM = { string_1, string_2, string_3, string_4 }; void main(void) { char buffer[10]; for (unsigned char i = 0; i <4; i++) { strcpy_P(buffer, (PGM_P)pgm_read_word(&(MainMen[i]))); LCD_STRING (buffer,0,i); } return; } Das hier funktioniert einwandtfrei. Also denk ich mal das ich irgendwas falsch gemacht hab bei der DrawMenu oder DoMenu Funktion.
Im übrigen ist es nicht besonders schlau, wenn du zuerst den kompletten String ins SRAM kopierst um dann eine vorhandene Ausgabefunktion aufzurufen. Es ist wesentlich vernünftiger, wenn du dir eine 2-te String Ausgabefunktion baust, die den String Zeichen für Zeichen eben nicht aus dem SRAM sondern aus dem Flash holt. Aber überarbeite erst mal deine LCD_STRING Funktion!
1 | void LCD_STRING (char *s,int x, int line) |
2 | {
|
3 | switch (line) |
4 | {
|
5 | |
6 | case 0: |
7 | {
|
8 | LCD_GOTO_XY(x,line); |
9 | while (*s) |
10 | {
|
11 | LCD_DATA1 (*s); |
12 | s++; |
13 | }
|
14 | break; |
15 | }
|
16 | case 1: |
17 | {
|
18 | LCD_GOTO_XY(x,line); |
19 | while (*s) |
20 | {
|
21 | LCD_DATA1 (*s); |
22 | s++; |
23 | }
|
24 | break; |
25 | }
|
26 | case 2: |
27 | {
|
28 | LCD_GOTO_XY(x,line); |
29 | while (*s) |
30 | {
|
31 | LCD_DATA2 (*s); |
32 | s++; |
33 | }
|
34 | break; |
35 | }
|
36 | case 3: |
37 | LCD_GOTO_XY(x,line); |
38 | while (*s) |
39 | {
|
40 | LCD_DATA2 (*s); |
41 | s++; |
42 | }
|
43 | break; |
44 | }
|
45 | }
|
Die Funktion ist mehr als ungeschickt gemacht und viel zu lang, für das was sie kann. Merke: Bau dir Basisfunktionen, die du gut benutzen kannst und viele Probleme auf höherer Softwareebene sind plötzlich keine Probleme mehr.
Ooops Geh das mal mit einem Wert für MenuSize von 4 durch
1 | void DrawMenu( uint8_t MenuSize, struct MenuEntry Menu[],PGM_P Strings[] ) // Display the Menu Entries |
2 | {
|
3 | char buffer[25]; |
4 | uint8_t i=0; |
5 | LCD_CLEAR(); |
6 | |
7 | if (MenuSize <4) // less then 4 entries in this menu ? |
8 | {
|
9 | ***** nicht der Fall .... |
10 | }
|
11 | |
12 | if (MenuSize >3 && MenuSize <8) // more then 4 and less then 8 entries ? |
13 | {
|
14 | |
15 | ***** passt: MenuSize > 3 |
16 | |
17 | LCD_CLEAR(); |
18 | for( i = 4; i < (MenuSize); ++i ) // loop until last entry reached |
19 | {
|
20 | |
21 | ***** Wie oft wird diese Schleife ausgeführt, wenn MenuSize einen Wert von 4 hat? |
22 | |
23 | ...
|
PS: Warum hast du eigentlich den String Pointer nicht gleich in dein struct MenuEntry mit aufgenommen? Da mit einem zusätzlichen Pointer Array zu hantieren ist nur eine zusätzliche Fehlerquelle mehr.
Das war das Problem. Danke für die schnellen Antworten. Ich hab den Source Code nochmal angehängt falls jemand sowas brauchen kann. Ausserdem habe ich auch versucht die Stringpointer in die Structure mit reinzupacken allerdings hat das nicht funktioniert. Hab ich den Absatz falsch verstanden ? Oder nur falsch umgesezt ? ->PS: ->Warum hast du eigentlich den String Pointer nicht gleich in dein struct ->MenuEntry mit aufgenommen? Da mit einem zusätzlichen Pointer Array zu ->hantieren ist nur eine zusätzliche Fehlerquelle mehr. Der neue Source ist auch im Anhang. Wäre super wenn jemand nochmal drüber schauen könnte. Vielen Dank schonmal.
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.