Hallo, ich steh grad bezüglich eines Zeigers etwas auf dem Schlauch. Ich habe in einem Array im Flash einen Zeiger auf eine Variable liegen. Diese will ich dann lesen oder verändern. uint8_t get_selection(uint8_t id) { uint8_t *foo = pgm_read_word(&menu[id].old_selection); return *foo; } Ändern der Variablen: void set_selection(uint8_t id, uint8_t value){ uint8_t *t = pgm_read_word(&menu[id].old_selection); *t = value; } wobei menu.old_selection vom Typ uint8_t* ist. Initialisiert habe ich old_selection mit &bar, wobei bar natürlich auch uint8_t ist. So klappt es aber nicht. Aber pgm_read_word liefert mir doch lediglich die Adresse der Variablen zurück, auf die menu.old_selection zeigt. Das muss ich doch dann de-referenzieren, um auf den Inhalt dieser Variablen zu kommen?? Gruß Mr.Green
In return *foo; ist doch deine Dereferenzierung (*), um auf den Inhalt zu kommen. Du solltest mehr Code angeben: Wie legst du menu[] an, wie speicherst du Werte darin und wie willst du die angegebenen Funktionen im späteren Code nutzen.
Das Menü bau ich aus einem struct auf: uint8_t sel_on_off; (die ist global, über ein extern) typedef struct { uint8_t id, next, prev, parent, child; char name[MENU_STRING_LENGTH]; uint8_t type; uint8_t int_part, fract_part; uint32_t max_int; void ( *fkt_pointer )( void ); uint8_t *old_selection; uint32_t *old_int; uint16_t *old_fract; } menu_t; Menu ist im Flash und logischerweise fest kodiert: menu_t menu[40] PROGMEM = { [...] {31, 28, 30, 4, 31, "LangeAuswahl4", TYPE_TEXT, 0, 0, 0, 0 &sel_on_off}}; Auf den Inhalt von sel_on_off will ich dann lesen bzw. schreibend zugreifen. Dazu hatte ich mir die Funktionen oben ausgedacht, die dem Compiler aber nicht so recht schmecken wollen. Das verunsichert mich etwas, weil die doch von der Theorie her so funktionieren sollten, oder nicht? Durch das pgm_read_word(...) erhalte ich doch erst die Adresse, an der dann der Inhalt von sel_on_off liegt. Oder ist da ein Denkfehler?
Ich sehe keinen Denkfehler. Der kann aber noch in dem Code stecken, der die Funktionen get_selection() und set_selection() verwendet. > menu_t menu[40] PROGMEM = { [...] > {31, 28, 30, 4, 31, "LangeAuswahl4", TYPE_TEXT, > 0, 0, 0, 0 &sel_on_off}}; ^ Wenn das (^) im Originalcode auch so ist, ist das ein fataler Fehler für dein Programm.
Ne da ist natürlich ein Komma. Da stand ein Funktionszeiger, der für meine Frage aber nicht relevant ist :) Muss ich denn vielleicht noch casten?
Simuliert auf dem Atmega8 wie erwartet:
1 | #include <avr/io.h> |
2 | #include <inttypes.h> |
3 | #include <avr/pgmspace.h> |
4 | |
5 | #define MENU_STRING_LENGTH 32
|
6 | #define TYPE_TEXT 2
|
7 | |
8 | uint8_t sel_on_off; |
9 | |
10 | typedef struct { |
11 | uint8_t id, next, prev, parent, child; |
12 | char name[MENU_STRING_LENGTH]; |
13 | uint8_t type; |
14 | uint8_t int_part, fract_part; |
15 | uint32_t max_int; |
16 | void ( *fkt_pointer )( void ); |
17 | uint8_t *old_selection; |
18 | uint32_t *old_int; |
19 | uint16_t *old_fract; |
20 | } menu_t; |
21 | |
22 | menu_t menu[2] PROGMEM = { |
23 | {31, 28, 30, 4, 31, |
24 | "LangeAuswahl4", |
25 | TYPE_TEXT, |
26 | 0, 0, |
27 | 0, |
28 | 0, |
29 | &sel_on_off, |
30 | 0, |
31 | 0
|
32 | }
|
33 | };
|
34 | |
35 | uint8_t get_selection(uint8_t id) { |
36 | uint8_t *foo = (uint8_t *) pgm_read_word(&menu[id].old_selection); |
37 | return *foo; |
38 | }
|
39 | |
40 | void set_selection(uint8_t id, uint8_t value){ |
41 | uint8_t *t = (uint8_t *) pgm_read_word(&menu[id].old_selection); |
42 | *t = value; |
43 | }
|
44 | |
45 | int main(void) |
46 | {
|
47 | uint8_t dummy; |
48 | |
49 | sel_on_off = 23; |
50 | |
51 | dummy = get_selection(0); |
52 | |
53 | if (dummy == sel_on_off) |
54 | dummy = 1; |
55 | else
|
56 | dummy = 0; |
57 | |
58 | set_selection(0, 42); |
59 | |
60 | dummy = get_selection(0); |
61 | |
62 | if (dummy == 42) |
63 | dummy = 1; |
64 | else
|
65 | dummy = 0; |
66 | |
67 | while(1); |
68 | }
|
Der Cast (uint8_t *) beseitigt nur eine Warnung, ist aber an dieser Stelle durchaus "legal".
Wow danke für die Arbeit!! An den Simulator habe ich gar nicht gedacht und mir den Kopf zerbrochen, wie ich das testen könnte :/
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.