Hallo C-Profis, ich habe folgendes Problem: Für ein Display-Menü habe ich mir ein Struct für die einzelnen Buttons gebaut in der Form: typedef const struct { unsigned char xpos; unsigned char ypos; ... void (*program)(); //Zeiger auf Funktion ... } but; Nun speicher ich die Werte in einem Array aus diesen Structs in den Flash: const but button[MAX_BUTTONS] PROGMEM = {{10,20,...,dimming_high,...}, {...}}; "dimming high" ist nun die Funktion, auf die der Zeiger im Struct zeigt. Verwende ich PROGMEM nicht und speicher das Array ganz normal, erreiche ich die Funktion folgendermaßen: (*button[index].program)(); Meine Frage ist jetzt, wie kann ich die entsprechende Funktion starten, wenn mein Zeiger im Flash liegt? Ist dies überhaupt möglich? Vielen Dank im voraus. Gruß Niklas
Ist offenbar ein AVR. Du musst eine Zeigervariable im RAM anlegen und diese mittels pgm_read_word() aus dem ROM füllen.
Hallo Jörg, entschuldige bitte, ich hatte vergessen zu erwähnen, dass es um einen AVR geht und ich ihn mit gcc programmiere. Meine Zeigervariable im RAM ist bereits im Struct vorhanden: void (*program)(); Ich weiß auch, dass ein Zeiger bei den AVRs 16bit groß ist und man ihn dementsprechent mit pgm_read_word() liest. Mit einem normalen Zeiger habe ich auch kein Problem, nur kenne ich die Syntax nicht, um einen Zeiger auf eine Funktion aus dem ROM zu lesen. Ich habe es mit (void*)pgm_read_word((&button[i].program)()); versucht, aber AVR-Studio meldet mir: error: called object '&button[i].program' is not a function ??? Irgendetwas mache ich also falsch. Weist du wie die Syntax richtig lauten müsste? Danke Gruß Niklas
Du versuchst den Zeiger bereits im ROM zu dereferenzieren, d. h. die Funktion aufzurufen. Lass einfach mal die runden Klammern weg. Der Typecast nach void * bringt auch nichts.
Jetzt mal so aus dem Bauch heraus...
1 | void (*prog)(void) = (void(*)(void))pgm_read_word(&(button[i].program)); |
2 | prog(); |
Du kannst nicht (void(*)(void))pgm_read_word(&(button[i].program))(); direkt aufrufen, weil pgm_read_word ein Makro ist.
Ich würde es so angehen (Ungetestet, nur hingeschrieben)
1 | typedef const struct { |
2 | unsigned char xpos; |
3 | unsigned char ypos; |
4 | ...
|
5 | void (*program)(void); //Zeiger auf Funktion |
6 | ...
|
7 | } but; |
8 | |
9 | // Definitionen
|
10 | |
11 | const but button[MAX_BUTTONS] PROGMEM = { |
12 | {10, 20, ..., &dimming_high, ...}, |
13 | {...}
|
14 | };
|
15 | |
16 | void dimming_high(void) |
17 | {
|
18 | }
|
19 | |
20 | // Aufruf
|
21 | |
22 | int main(void) |
23 | {
|
24 | // so ;-)
|
25 | void (* fptr)(void); |
26 | fptr = (void (*)) pgm_read_word((&(button[0].program)); |
27 | fptr(); |
28 | |
29 | // oder so ;-(
|
30 | *((void (*)) pgm_read_word((&(button[0].program)))(); |
31 | }
|
EDIT: Mit Werners Antwort hat sich mein ;-( erledigt ;-)
Es funktioniert!!! Ich danke euch vielmals für eure Hilfe! Ich habe mein Fehler erkannt. Eigentlich blöde von mir zu versuchen, eine Adresse zu "starten". Habe die Adresse der Funktion jetzt an einen neuen Funktionszeiger übergeben, wie von euch vorgeschlagen und es funktioniert auf Anhieb. Nochmals danke. Gruß Niklas
> // oder so ;-(
Versuch mal, diesen Smiley mit deinem Gesicht nachzumachen, also die
Mundwinkel hängen lassen und ein Auge zukneifen. Ist gar nicht so
einfach ;-)
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.