Morgen! Ich grüße Euch!
Ich habe ein kleines Problemchen und hoffe, daß mir jemand helfen kann.
Ich versuche krampfhaft ein Menü für mein Display zu erstellen.
Ich bekomme aber immer eine Fehlermeldung :
main.c:44: error: expected ';', ',' or ')' before 'MainMenu'
Bei dieser Zeile:
...
void DoMenu( int NrEntries, struct MenuEntry[] Menu )
...
Hier ist der Code:
( habe ich von
http://www.mikrocontroller.net/articles/FAQ#Me%C3%BCs%20mit%20Funktionszeiger
)
Kann mir jemand sagen warum ?
Danke im voraus.
Sven D. wrote:
> Ich bekomme aber immer eine Fehlermeldung :> main.c:44: error: expected ';', ',' or ')' before 'MainMenu'>> Bei dieser Zeile:>> ...> void DoMenu( int NrEntries, struct MenuEntry[] Menu )> ...
Das kanns nicht sein. In dieser Zeile kommt kein einziges mal der
Begriff MainMenu vor. Schau mal in die unmittelbar vorhergehende Zeile.
> Hier ist der Code:> ( habe ich von> http://www.mikrocontroller.net/articles/FAQ#Me%C3%BCs%20mit%20Funktionszeiger> )
Das kann nicht der vollständige Code sein. Dort sind lediglich ein paar
Fragmente.
> Kann mir jemand sagen warum ?
entweder du hast irgendwo einen Tippfehler und dich bei einem Namen
vertippt oder die STrukturdefinition ist nicht vor der ersten Verwendung
oder der eigentliche Fehler ist ganz was anderes und die Fehlermeldung
ist missverständlich oder ....
Zeig den ganzen Code, dann kann man mehr sagen.
Danke Stefan.
Das hat mich weiter gebracht. Fehler ist weg.
Jedoch mein Menü klappt überhaupt nicht.
Hast Du Erfahrungen mit einfachen one level Menüs???
Sind überhaupt Funktionszeiger das Richtige?
Wozu brauchst du dir for-Schleife, wenn du dann sowieso die Menütexte
hardcoded hinschreibst?
1
if(PIND&(1<<PIND2)){Auswahl=1;}
2
if(PIND&(1<<PIND3)){Auswahl=1;}
3
4
5
if(PIND&(1<<PIND4))//Taster 3
6
return;
7
8
Auswahl=Auswahl-1;
9
if(Auswahl<0||Auswahl>NrEntries)
Die Art und Weise wie 'Auswahl' hoch bzw. runter gezählt wird, solltest
du nochmal überdenken. Edit: Wo wird Auswahl eigentlich hoch gezählt?
> Sind überhaupt Funktionszeiger das Richtige?
Klar sind sie das. Aber die Funktionspointer sind ja noch gar nicht dein
Problem. Dein ganzer Textaufbau bzw. Auswertung von Tastendrücken stimmt
hinten und vorne nicht.
Wenn dir das ganze Menü noch zu undurchsichtig ist, dann gehs
schrittweise an. Konzentrier dich einfach mal nur darauf, die Texte aus
dem Array korrekt anzuzeigen. Und erst dann, wenn das klappt, kümmerst
du dich um die Tastenauswertung. Und wenn das klappt, kümmerst du dich
darum, dass die richtige Funktion aufgerufen wird.
Ok Karl.
Ich werde es so angehen wie du das vorgeschlagen hat.
Du hast Recht. Ich habe einfach ein Code aus dem Tutorial kopiert,
ohne zu wissen was da eigentlich passiert.
Ich fange also alles wieder von vorne an.
Könntest du mir ein bißchen behilflich sein? Ein Kopfnicken reicht aus.
1. Der Aufbau
Mein Menü besteht aus 4 Menüpunkten. One Level d.h. Keine Untermenüs
--------------
Menüpunkt 1
Menüpunkt 2
Menüpunkt 3
Menüpunkt 4
--------------
Ich habe 3 Taster zu Verfügung.
Taster 1. nach oben (optisches hervorheben des menüpunktes z.B. rechteck
drumrum )
Taster 2. nach unten (optisches hervorheben der menüpunktes z.B.
rechteck drumrum )
Taster 3. Bestätigen der Auswahl.
läßt sich das auch mit switch realisieren oder mit normalen if abragen?
Was wäre sinnvoller ???
Vielen Dank für alle Anregungen
Sven D. wrote:
Die erste Frage, die du dir stellen musst, lautet:
Brauche ich ein universelles Menüsystem (so wie du das aus der FAQ
übernommen hast) oder reicht etwas ganz simples.
Da du anscheinend nur 1 Menü hast und für jeden Menüpunkt feststeht was
er zu tun hat und es keinerlei sontigen Problemkreise gibt, würde ich
mal sagen: Es reicht etwas ganz Simples.
Das bedeutet: Du brauchst kein grossartiges Array mit Texten.
Mach dir eine Funktion, die die 4 Texte an die korrekten Positionen
hinschreibt und fertig.
Dann solltest du dir überlegen, wie du herausstellst, welcher Menüpunkt
momentan der aktive ist. Aktiv in dem Sinne, dass dieser Menüpunkt
gewählt wird, wenn der Benutzer die entsprechende Aktion (meist das
Drücken eines Buttons) wählt. Wie du das machst ist deien Sache, ich
schlage jetzt der Einfachheit halber mal vor, dass der entsprechende
Menüpunkt in der 1. Spalte ein '*' erhält. Die Auswertung der
Tastendrücke für rauf und runter bedeutet daher nichts anderes, als das
natürlich mitgezählt werden muss, in welcher Zeile man gerade ist, und
dass dieser '*' seinen Platz wechseln muss. Am einfachsten geschieht
dies, indem in allen 4 möglichen Zeilen in der *-Spalte ein Leerzeichen
geschrieben wird und dann der * in der richtige Zeile in die *-Spalte
platziert wird.
Also fangen wir mal an. Du brauchst eine Funktion, die die Menüpunkte
ausgibt. Dabei berücksichtigen wir gleich mal, dass es eine *-Spalte
geben wird und legen diese als Spalte 1 fest. Die Texte können also
frühestens in Spalte 2 anfangen
1
voidDrawMenuTexts()
2
{
3
lcd_set_cursor(2,LINE2);
4
lcd_puts_p(small_font,PSTR("MENÜPUNKT 1"));
5
6
lcd_set_cursor(2,LINE3);
7
lcd_puts_p(small_font,PSTR("MENÜPUNKT 2"));
8
9
lcd_set_cursor(2,LINE4);
10
lcd_puts_p(small_font,PSTR("MENÜPUNKT 3"));
11
12
lcd_set_cursor(2,LINE5);
13
lcd_puts_p(small_font,PSTR("MENÜPUNKT 4"));
14
}
Und gleich mal ausprobieren!
....
Was brauchst du noch. Eine Funktion, die den * richtig platziert.
Dazu braucht die Funktion die Kenntnis, welche Zeile die auszuwählende
ist. Gut, damit wissenb wir welche Parameter die Funktion haben wird,
nämlich die Nummer des Menüpunktes. Wie in C üblich, soll dabei die
Zählung der Menüpunkte bei 0 beginnen.
Was hat sie zu tun: Alle *-Spalten löschen und in die korrekte (die mit
dem übergebenen Menüpunkt) einen * setzen.
Na das sollte doch nicht allzu schwer sein.
1
voidActivateEntry(uint8_tNr)
2
{
3
lcd_set_cursor(1,LINE2);lcd_putc(' ');
4
lcd_set_cursor(1,LINE3);lcd_putc(' ');
5
lcd_set_cursor(1,LINE4);lcd_putc(' ');
6
lcd_set_cursor(1,LINE5);lcd_putc(' ');
7
8
lcd_set_cursor(1,LINE2+Nr);lcd_putc('*');
9
}
Ausprobieren !
1
intmain()
2
{
3
....
4
5
DrawMenuTexts();
6
ActivateEntry(0);
7
8
while(1)
9
;
10
}
Wenn du jetzt beim ActivateEntry Aufruf in main() andere Werte von 0 bis
3 eingibst, muss der * in jeweils einer anderen Zeile auftauchen!
Auch mal einen anderen Test machen
1
intmain()
2
{
3
uint8_tActive;
4
5
....
6
7
DrawMenuTexts();
8
9
Active=0;
10
while(1){
11
ActivateEntry(Active);
12
Active++;
13
if(Active==4)
14
Active=0;
15
16
delay_ms(1000);
17
}
18
}
Der * muss im Sekundentakt von einer Zeile zur nächsten hüpfen.
Wenn das klappt, ist der nächste Teil drann: Abfrage der Tasten und eine
Variable, nenn sie ruhig weiter Active, je nach Tastendruck entweder
erhöhen oder verringern. Dabei aufpassen, dass die Grenzen 0 und 3
eingehalten werden. Nach jeder Veränderung von Active wird ActivateEntry
aufgerufen, damit der * in die richtige Spalte hüpft.
1
voidHandleButtons()
2
{
3
uint8_tActive=0;
4
5
ActivateEntry(Active);
6
7
while(1)
8
{
9
if(PIND&(1<<PIND2))
10
{
11
if(Active<3)
12
{
13
Active++;
14
ActivateEntry(Active);
15
}
16
}
17
18
if(PIND&(1<<PIND3))
19
{
20
if(Active>0)
21
{
22
Active--;
23
ActivateEntry(Active);
24
}
25
}
26
}
27
}
Neues main schreiben und das ganze testen!
1
...
2
intmain()
3
{
4
...
5
6
DrawMenuTexts();
7
HandleButtons();
8
}
Tja. und jetzt tut sich ein neues Problem auf. Die Abfrage der Tasten
ist so untauglich. Die Schleife in HandleButtons wird viel zu schnell
abgearbeitet, als das du gezielt einen Menüpunkt auswählen kannst. Was
ist das Problem: Die entsprechenden Active-Erhöhungen/Erniedrigungen
werden nicht ausgeführt wenn eine Taste gedrückt wird, sondern
solange eine Taste gedrückt ist. Und das rasend schnell.
Also wird das jetzige Projekt mal zur Seite gelegt und ein neues
Testprojekt angefangen um dieses Problem zu studieren und eine Lösung
dafür zu finden.
Keine Sorge: In der Codesammlung existiert dazu was. Schau einfach mal
rein, eigentlich müsstest du das finden
Wenn du dann weist, wie man das richtig macht, dann baust du das in
obiges ein und .... testest erst mal, ob das ganze benutzbar ist.
Und so geht das Schritt für Schritt weiter.
Fällt dir was auf. Bis jetzt sind sicherlich schon ein paar Stunden
vergangen, und wir haben uns bisher noch keinerlei Gedanken darüber
gemacht, was denn eigentlich passieren soll, wenn ein Menüpunkt
aktiviert wird :-)
Daher ist die Frage, ob du besser if-then-else oder switch-case nimmst
eine Frage, die sich im Moment für dich noch gar nicht stellt. Du hast
jetzt am Anfang ganz andere Dinge zu tun. Aber: Wenn du schrittweise an
die Sache rangehst, dann wirst du irgendwann ein fertiges Menü haben.
Oj Oj Oj.
Danke Dir Karl. Das sind schon mal sehr gute Vorschläge.
Ich muß mir das erstmal genau anschauen, und dann versuche ich
mein Glück. Ich melde mich heute Abend und sage wie weit ich bin.
Aber vorerst möchte ich mich für die vielen Tips bedanken.
Bis später.
P.S. @Karl.
MAchst Du das alles hobbymäßig oder beruflich? Du scheinst ja wirklich
viel darüber zu wissen...
Gruß
Hallo an Alle!
Besonderes Hallo an Karl! Du hast es drauf :o)
Ich wollte mich nochmal herzlich bedanken.
Dein Code war wirklich super. Eigentlich hast Du alles nötige gemacht.
Ich habe es noch ein bißchen erweitert und das Problem so gelöst.
Es ist nicht optimal aber es funktioniert.
Vielleicht hilft es irgendwann Jemanden, der solch ein einfaches Menü
sucht...
Falls Du eine optimalere Lösung hast, ich bin für alle Vorschläge offen.