Hallo, Folgendes Problem: Ich habe eine Verkettete liste angelegt mit daten gefüllt und diese is Flash gelegt. typedef const struct PROGMEM MENU_STR { const struct PROGMEM MENU_STR *sub_menu; CALL_FUNC MenuFuncPtr; const unsigned char text_u8 [15]; }MENU_STRUKTUR; MENU_STRUKTUR sub_test1 [MENU_MAX] ={ {NULL , move_midas_logo,"Demo1_t"}, {NULL , foo ,"sub menu"}, {NULL , sw_stand ,"SW_St_t"}, {NULL , sm_reset ,"RESET_t"}, {NULL , sm_sleep ,"Sleep_t"} }; MENU_STRUKTUR Main_Menu_Table_MenStr [MENU_MAX] ={ {sub_test1 , move_midas_logo , "Demo1"}, {sub_test1 , change_menu , "sub_menu"}, {NULL , sw_stand , "SW_St"}, {NULL , sm_reset , "RESET"}, {NULL , sm_sleep , "Sleep"} }; Soweit so gut ! wenn ich jetzt ein Array von Pointern erstelle und diese Auf mein Strktur array zeigen lasse: MENU_STRUKTUR *CurrentMenu_MenStr_ptr[MENU_MAX]; for (i_u8= 0; i_u8 < MENU_MAX; i_u8++) { CurrentMenu_MenStr_ptr[i_u8]= &Main_Menu_Table_MenStr[i_u8]; } Will ich jetzt auf den Text zugreifen: pgm_read_byte(CurrentMenu_MenStr_ptr[1]->text_u8); //kalppt ! will ich aber auf den text meies sub_menus zugreifen klappt das nicht pgm_read_byte(CurrentMenu_MenStr_ptr[1]->sub_menu[1].text_u8); //klappt nicht Warum geht das so nicht? Wenn ich das ganze im Ram mache geht es. Danke!!
DrKarlTheodor schrieb: > pgm_read_byte(CurrentMenu_MenStr_ptr[1]->text_u8); //kalppt ! Hier dereferenzierst du einmal. Zur Compile-Time sind alle relevanten Grössen bekannt, deshalb musst du nur einmal via pgm_read_byte eingreifen, um aus dem Flash zu lesen. > will ich aber auf den text meies sub_menus zugreifen klappt das nicht > pgm_read_byte(CurrentMenu_MenStr_ptr[1]->sub_menu[1].text_u8); //klappt > nicht Hier liegt der Fall etwas anders, da du Pointer auf Pointer hast. Du musst "zu Fuss" dereferenzieren bzw. die Pointer aus dem Flash lesen (pgm_read_word). Jetzt dereferenzierst du "übers RAM" und landest irgendwo im Flash!
Ich verstehe das so, dass ich erst den die Pointer mit pgm_read_word lesen muss. z.B. so: MENU_STRUKTUR *test [5] test [1] = pgm_read_word( &CurrentMenu_MenStr_ptr[1]->sub_menu[1]); und dann mit pgm_read_byte das zeichen aus dem String pgm_read_byte(test[1]->text[1]); das funktioniert so aber nicht.
DrKarlTheodor schrieb: > Ich verstehe das so, dass ich erst den die Pointer mit pgm_read_word > lesen muss. > z.B. so: > MENU_STRUKTUR *test [5] > test [1] = pgm_read_word( &CurrentMenu_MenStr_ptr[1]->sub_menu[1]); Du kannst hier keinen -> benutzen! Mal dir die Situation auf
1 | Current... F Main_Menu_Table_MenStr |
2 | +-----------+ +-----------------+ |
3 | | o------------------------>| o---------------------+ |
4 | +-----------+ | move_midas_logo | | |
5 | | o------------------+ | "Demo1" | | |
6 | +-----------+ | +-----------------+ | F sub1 |
7 | | o---------------+ +----->| o-----------------+ | +--------------------+ |
8 | +-----------+ | | change_menu | | +--->| * NULL | |
9 | | o-------------+ | | "sub_menu" | +------->| * move_midas_logo | |
10 | +-----------+ | | +-----------------+ | * "Demo1_t" | |
11 | | o----------+ | +-------->| NULL | +--------------------+ |
12 | +-----------+ | | | sw_stand | | * NULL | |
13 | | | | "SW_St" | | * foo | |
14 | | | +-----------------+ | * "sub menu" | |
15 | | +---------->| NULL | +--------------------+ |
16 | | | sm_reset | | * NULL | |
17 | | | "RESET" | | * sw_stand | |
18 | | +-----------------+ | * "SW_St_t" | |
19 | +------------->| NULL | +--------------------+ |
20 | | sm_sleep | | * NULL | |
21 | | "SLEEP" | | * sm_reset | |
22 | +-----------------+ | * "RESET_t" | |
23 | +--------------------+ |
24 | | * NULL | |
25 | | * sm_sleep | |
26 | | * Sleep_t" | |
27 | +--------------------+ |
Das ist die Datenstruktur, die du da zusammengebaut hast. Mal abgesehen davon, dass sie nicht seh sinnvoll ist (das Array Current... braucht in Wirklichkeit kein Mensch) sieht man eines: Immer dann, wenn du, um an die Daten zu kommen einem Pfeil folgen musst, an dessen Ende ein Kasten steht, der links oben mit einem "F" (wie Flash) markiert ist, dann kannst du nicht -> oder * benutzen, sondern musst die Adresse an pgm_read.... übergeben und diese Funktion besorgt dir dann die Daten. CurrentMenu_MenStr_ptr[1]->sub_menu[1]); CurrentMenu_MenStr_ptr das ist ok. Der zugehörige Kasten hat kein F, daher ist CurrentMenu_MenStr_ptr[1] in Ordnung. Von dort geht ein Pfeil weg. Sowohl in der Zeichnung als auch in deinem Programm: CurrentMenu_MenStr_ptr[1]-> Mööp. Ein BLick in die Zeichnung verrät: Der Pfeil endet in einem Block, der 'F' markiert ist, die Daten liegen also im Flash. Daher kannst du hier nicht -> benutzen, sondern musst mittels pgm_read_.... den dich interessierenden Teil holen. Was willst do holen? Einen Pointer, also 2 Bytes, also ist pgm_read_word dein Freund.
1 | tmp = pgm_read_word( CurrentMenu_MenStr_ptr[1] + offsetof( sub_menu ) ); |
Damit hast du jetzt in tmp den Pointer aus dem Flash geholt, der auf das sub1 zeigt (in diesem Fall). sub1 ist selber wieder im Flash (ist 'F' markiert). Um also an Werte in diesem Block ran zu kommen auf den du einen Zeiger hast, muss wieder eine pgm_read.... Funktion bemüht werden. Wenn du bei verzeigerten Datenstrukturen den Überblick verlierst, wie sie aussehen, DANN MAL DIR DIE SITUATION AUF PAPIER AUF! Wenn du dann noch markierst, welche Teile im SRAM liegen und welche im Flash, dann kannst du ganz leicht entscheiden, wie der Zugriff aussehen muss. Die Zeichnung leitet dich.
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.