@all, ich habe nun schon einige Beiträge hier im Forum durchgeschaut zum Thema Menüsteuerung. Habe zwar einiges gefunden jedoch auch viele wiedersprüchliges. Nun habe ich mich entschlossen einen neuen Beitrag zu starten. Zum einen habe ich vieles mit einer Strukurierten Programmierung (Struktur) gefunden. Ein weiterer Beitrag schlägt eine state machine mit switch-case operator vor. Ich habe zwar noch keine Strukturen programmiert jedoch die Idee gefällt mir recht gut. Leiter sieht es mit source codes oder Codeschnipsel recht mager aus. Eventuell kann ja jemand der sowas schon gemacht hat mal was posten. In einem Beitrag der über Strukturen ging wurde der Butterfly von Atmel genannt und man solle sich mal diesen Code anschauen. Ich habe mir diesen mal heruntergeladen und ich denke da ist schon was dabei um Denkanstöße zu liefern. Bevor ich mich jetzt für eine Variante entscheiden möchte ich mich mal nach Euren Meinungen/Erfahrungen erkundigen. Ich hänge mal die Headerfiles vom Butterfly an. Was meint Ihr zur Menu.h könnte man so programmieren? Gruß Und schon mal DANKE für die Antworten. Thomas
Das wichtigste an Menusteuerung ist immer noch die Orientierung dieser Steuerung am Benutzer. Da kann es dann sein, dass die Bedienung mittels total flacher Eingabe numerierter Parameter besser ankommt als ein noch so schön programmierter Menuebaum, weil Nummern per Zettel daneben kein Problem sind, aber der Menubaum sofort ein undurchdringliches Labyrinth wird. Wenn der Benutzer zu jeder Sorte Menschen gehört, die beim Telefonieren per Handy für alles was über das Eintippen der Ziffern hinausgeht ein Flussdiagramm brauchen, ist jedes Menu schon im Ansatz verkehrt. Und solche Menschen gibt es sehr viele.
ich hab mir mal die state machine aus dem AVR Butterfly ausgelötet und verwende das - das ist ganz brauchbar; vor allem ist es daten-gesteuert. Labyrinthe sind möglich, aber optional :) -Michael
@Andreas, vermutlich min ich der einzige Benutzer.Daher muss nur ich mich auskennen. Es sollten eigentlich nur Parameter geändert bzw. hinzugefügt werden. Das ganze 5 Tasten RECHTS-LINKS-HOCH-RUNTER-OK. Zum Menü noch ein paar Worte. Im Hauptmenu 5-8 Menüpunkte und in den Untermenüs jenachdem 3-8 Menüpunkte. Das ganze bis max. 3 Untermenüs. Ich möchte nur etwas anfangen was ich später auch leicht ergänzen kann ohne das ganze wieder komplett umschreiben zu müssen.Es sollte einfach erweiterbar sein daher die Strukturvariante. Da ich das eine noch das andere schon gemacht habe kann ich mich nicht entscheiden.
@all, ich habe mich nun für die Strukturvariante entschlossen. Hatte mich heute zum ersten Mal mit Strukturen beschäftigt und die Headerfiles von oben zur Grundlage genommen. Ist zwar etwas gewöhnungsbedürftig aber eigentlich leichter als ich gedacht habe. Habe nun ein Menu erstellt mir Untermenüs etc. und es funktioniert. Einfach klasse!!!! :-) Danke an alle für die Hilfestellungen. Thomas
Hallo, ich habe nun meine Steuerung soweit gebracht das ich auch Funktion ausführen kann. Nun wollte per menu ein uchar Array[20][40] auslesen und dabei immer 4 Werte gleichzeitig anzeigen und ändern. z.B. zuerst Array[0][x] - Array[3][x] danach Array[4][x] - Array[7][x] danach Array[8][x] - Array[11][x] usw. Danach die zweite Zeile (x). Im array gibt es max 40 Datensätze es können auch weniger sein und das ist mein Problem. Wie kann ich Menu es machen das wenn nur 6 Datensätz enthalten sind nach dem anzeigen des 6 Datensatzes das menu nicht auf 7 springt sondern wieder auf 1 also Datensatz 1-->2-->3-->4-->5-->6-->1 usw. Also flexibel. Thomas
Deine Beschreibung ist nicht sehr klar. Aber ich versuche mal einen Schuss ins Blaue. Du brauchst eine Variable, die dir die tatsächliche Anzahl angibt. In deinem konkreten Fall also die 6 Du wirst dann wahrscheinlich eine Funktion haben, die dir immer 4 Einträge aus deinem Array anzeigt und zumindest einen Button für 'Weiter' (der dann die nächsten 4 Einträge anzeigt) Kern dieser Funktion ist die Schleife, die immer 4 Einträge anzeigt:
1 | void foo( ... ) |
2 | {
|
3 | ....
|
4 | |
5 | FirstEntry = 0; // welches ist der erste anzuzeigende Eintrag |
6 | |
7 | ....
|
8 | |
9 | do { |
10 | |
11 | for( i = FirstEntry; i < FirstEntry + 4; ++i ) { |
12 | // gib den Eintrag i aus
|
13 | |
14 | if( i + 1 == NrTotalEntries ) // das wars, mehr gibts nicht |
15 | break; |
16 | }
|
17 | |
18 | if( Button_Next_Pressed && FirstEntry + 4 < NrTotalEntries ) |
19 | FirstEntry += 4; |
20 | |
21 | } while( !MenuFinished ) |
da ich die Details deines Menüsystems nicht kenne, ist obiges als Pseudocode zu sehen, der dir eine Idee gibt, wie du die Anzahl der Menüeinträge insgesamt einbauen kannst/sollst/musst. Kann auch sein, dass ich da jetzt irgendwo um +- 1 bei den Arrayindizes daneben bin, ich wollte nur die Idee skizzieren, die Details überlasse ich dir :-)
@ Karl Heinz, vielen Dank für Deine Unterstützung hat wunderbar geklappt mit dem flexieblen auslesen von Daten. Wenn ich nun die angezeigten Werte ändern will wie machen ich das am besten. 1. Auf den Display ändern und dann die Daten von Display auslesen und im Array speichern --> Habe irgentwo gelesen das dies funktioniert jedoch noch nie getestet. 2. Virtuell im Display ändern jedoch direkt den Arraywert ändern und das Display mit dem neuen Wert reloaden. 3. .....? Was ist am besten geeignet? Ich habe bis jetzt mir 4 Tasten gearbeitet Hoch Runter Rechts Links um durch die Menüs zu zippen.. Wie es mir jedoch scheind brauche ich nun noch weitere 4 Tasten Rechts Links um den Curser zu bewegen (arbeite nur auf einer Zeile mit den Werten) Hoch Runter um die Werte zu ändern. Sehe ich das Richtig ? Ich denke wenn ich es nicht mache gibt es einen richtigen durcheinander. Gruß und DANKE schon mal. Thomas
Thomas S. wrote: > Wenn ich nun die angezeigten Werte ändern will wie machen ich das am > besten. > > 1. Auf den Display ändern und dann die Daten von Display auslesen und im > Array speichern --> Habe irgentwo gelesen das dies funktioniert jedoch > noch nie getestet. Würde ich so nicht machen. > 2. Virtuell im Display ändern jedoch direkt den Arraywert ändern und das > Display mit dem neuen Wert reloaden. Das ist der Weg den ich gehen würde > Ich habe bis jetzt mir 4 Tasten gearbeitet Hoch Runter Rechts Links um > durch die Menüs zu zippen.. > Wie es mir jedoch scheind brauche ich nun noch weitere 4 Tasten > Rechts Links um den Curser zu bewegen (arbeite nur auf einer Zeile mit > den Werten) > Hoch Runter um die Werte zu ändern. > > Sehe ich das Richtig ? Du brauchst auf jeden Fall noch eine 'Auslösetaste'. Mit den Pfeiltasten navigierst du einen Eintrag an und mit der Auslösetaste wird der, dem Meüpunkt zugeordnete, Eintrag aktiviert. Ob ich da jetzt rauf/runter/rechts/links machen würde. Bin mir nicht sicher, aber ich denke nicht. Ich würde versuchen mit 3 Tasten auszukommen: Rauf, Runter, Return die Rauf / Runter Tasten navigieren durch das Menü Menüpunkt 1 Menüpunkt 3 Menüpunkt 2 Menüpunkt 4 Angenommen der Cursor steht auf 1. Einmal 'Runter' drücken bringt mich zur 2. Nochmal Runter -> 3, Nochmal -> 4. Beim nächsten Druck auf Runter erfolgt ein Umscrollen des Displays Menüpunkt 3 Menüpunkt 5 Menüpunkt 4 Menüpunkt 6 und die Auswahlmarkierung steht bei der 5. Druck auf 'Runter' -> es geht zur 6. Nochmal Runter -> Umscrollen und Cursor steht auf 7, etc. Sinngemäß alles umgekehrt bei einem Druck auf 'Rauf'. Bei meinem letzten Menü auf einem 2-zeiligen LCD hab ich überhaupt die Dinge anders gemacht. Die 1. Zeile ist eine Art Überschrift, quasi der Menüpunkt die 2. Zeile ist exklusiv für ev. Eingaben in diesem Menüpunkt reserviert. Dazu 3 Taste: Links, Rechts und Auslöser Das Menü sieht zb so aus > Name Kalle (Der Haken zeigt an, an welcher Stelle der nächste Tastendruck wirkt) Name ist der Menüpunkt, Kalle ist der zugehörige Wert Drücke ich jetzt 'Rechts' so wird der nächste Menüpunkt sichtbar > Akku LiPo Ein Druck auf Auslöser, lässt den Haken in die 2. te Zeile wechseln Akku > LiPo wo ich dann, wieder mit den Links/Rechts Tasten einen anderen Wert auswählen kann Akku > NiCd Wieder Auslöser drücken, aktiviert diesen Punkt und der Cursor-Haken geht wieder nach oben > Akku NiCd wo mich dann ein Druck auf Links wieder in die Ausgangssituation zurückbringt > Name Kalle Ich denke, dass man Menüfuhrungen mit dem begrenzten Platz und Tastenangebot, das man auf einem µC mit LCD hat, sowieso meistens an das jeweils zu bauende Gerät anpassen muss/soll. Die Universal- techniken, wie man sie auf einem PC benutzt, greifen hier nicht so recht.
@Karl Heinz, Danke mal wieder für Deine Antwort finde ich echt Klasse. Ich habe eine 5 Tasten Version mal versucht. Hoch Zurück Enter Weiter Runter Soweit funktioniert es schon zumindest die ersten Versucht. Bis jetzt habe ich immer nichts zu den nicht benutzten Tasten geschrieben, das war vermutlich ein Fehler. Wenn ich mal versehentlich eine Falsche drücke springt das Menü irgentwo hin. Naja aus Fehlern lernt man ja. Werde mir heute mal eine längere Nacht gönnen. Gruß Thomas
@Karl Heinz, bin etwas Ratlos was ich mit den nicht benötigten tasten machen soll? Teilweise navegiere ich mit alle Tasten und in bestimmten Untermenus benötige ich eben nur 1,2 oder 3 Tasten da dort die Auswahl begrenzt ist. Drücke ich aber an dieser Stelle ein falsche nicht definierte Taste springt das Prog immer in den letzten ausgeführten Menupunkt. Kann man einen pseudo Menupunkt erstellen der einfach nichts tut aber wie geht hier die Lösung? OK die einfachste währ immer die richtige Taste drücken jedoch das ist etwas schwierig. Jedoch bei der menu.h oben gepostet gibt es auch Menupunkte die nur mit einer Taste belegt sind und das ist ja von Atmel. Gibt es dort nicht dieses Phänomen?!? Eventuell liegt es auch an meiner Programmierung Ich habe nun die *.c Dateien von Butterfly nochmals angeschaut. Dort wird immer die Tastercode übertragen und in der Funktion zu Schluss nochmals geprüft, wenn dieser nicht übereinstimmt wird eine Ebene nach OBEN gesprungen. Nun habe ich auch folgenden code gesehen und dieser ist mit nicht ganz klar bzw ich habe nur eine Vermutung was passiert.
1 | else if (input == KEY_ENTER) |
2 | {
|
3 | enter = 1; |
4 | return ST_TIME_CLOCK_FUNC; |
5 | }
|
6 | return ST_TIME_CLOCKFORMAT_ADJUST_FUNC; |
Der Auszug ist aus einer Funktion. Wenn jetzt KEY_ENTER erfüllt ist wird der return ST_TIME_CLOCK_FUNC zurückgegeben. Was passiert dann mit dem
1 | return ST_TIME_CLOCKFORMAT_ADJUST_FUNC; |
Wird dieser übersprungen und nicht ausgeführt?!?!? :-) In dieser Art sind alle Funktionen aufgebaut, alle nicht benutzten Tasten sind so abgefragt bzw. so ähnlich. Gruß Thomas
@ Thomas S. (thomass) >Drücke ich aber an dieser Stelle ein falsche nicht definierte Taste >springt das Prog immer in den letzten ausgeführten Menupunkt. Es darf keine undefinierten Tasten geben. Die unbenutzten müssen halt ne Dummyfunktion auslösen, die keinerlei Wirkung hat. MFG Falk
hallo thomas, hättes du vllt eine aktuelle version von deinem menü? danke schon mal, grüße, holli
@Michael, also schon wieder Menusteuerung. Ich habe eigentlich nichts anderes gemacht als mit die AVR Butterfly Programmierung angeschaut und verstanden wie es dort gemacht wird. Diese kannst Du herunterladen unter http://www.atmel.com/dyn/resources/prod_documents/AVRButterfly_application_rev07.zip http://www.atmel.com/dyn/Products/tools_card.asp?tool_id=3146 --> AVR Butterfly - Application Rev07 (64 KB, updated 01/07) Hier sind im Prinzip drei Dateien zum ersten die menu.h und dieser ist die Struktur der Menusteuerung definiert. Also wenn Du im Menu1 bist und next drückst dann ins Menu 1.1 wechselst bei einer gedrückten PLUS Taste wechselst Du ins Menu 2 usw. Das musst Du Dir mal anschauen ist eigentlich recht simpel und gut verständlich. Die 2 Datei ist die Main.c in dieser musst Du dir eigentlich nur anschauen wie das Menu.h ausgerufen wird ich glaube es läuft alles über Funktionspointer. Es ist alles mit einer Art Tasterurmatrix programmiert. Die 3 Datei ist die eigentlich sind diese verstreut auf mehrere Dateien. Es ist im Prinzip die Funktion die ausgeführt werden soll bei einem bestimmten Menupunkt. Hier mal ein Auszug aus der Menu.h:
1 | MENU_STATE menu_state[] = { |
2 | // STATE STATE TEXT STATE_FUNC
|
3 | {ST_AVRBF, MT_AVRBF, NULL}, |
4 | {ST_AVRBF_REV, NULL, Revision}, |
5 | {ST_TIME, MT_TIME, NULL}, |
6 | {ST_TIME_CLOCK, MT_TIME_CLOCK, NULL}, |
7 | {ST_TIME_CLOCK_FUNC, NULL, ShowClock}, |
8 | {ST_TIME_CLOCK_ADJUST, MT_TIME_CLOCK_ADJUST, NULL}, |
9 | {ST_TIME_CLOCK_ADJUST_FUNC, NULL, SetClock}, |
10 | {ST_TIME_CLOCKFORMAT_ADJUST, MT_TIME_CLOCKFORMAT_ADJUST, NULL}, |
11 | {ST_TIME_CLOCKFORMAT_ADJUST_FUNC, NULL, SetClockFormat}, |
Es sind 3 Spalten die erste ist der Menupunkt z.B 1.0,1.1,1.1.1,1.1.2 usw die 2 Spalte ist der definierte Text der auf dem Display angezeigt werden soll ist weiter oben definiert. Die 3 Spalte sind die Funktionen die beim jeweiligem Menupunkt ausgeführt wird. Ich habe diese alle in ein Funk_Display.c gepackt. Achja eines noch, war mir am Anfang nicht ganz klar weshalb bei jeder Funktion die tasterturauswertung übergeben wird dies ist jedoch wichtig das es immer definiert ist was innerhalb der Funktion bearbeitet werden soll.Also unterschiedliche Dinge je Taste. Dies ist wichtig da Du von verschiedenen Menupunkten in ein Menu kommen kannst.Eventuell soll ja ein Wert mit plus minus verändert werden d.h Du bist immer im gleichen Menu jedoch mit einem Plus addierst Du und mit Minus Subtrahierst Du. Ich hoffe es ist verständlich. :-) Wenn nicht melde Dich nochmal. Mein Menuaufbau ist nur etwas komplizierter da ich ein 4x40 Display habe daher immer 2 Texte da 2 Controller. Thomas
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.