PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Menü - ich krieg die Krise!!!



dl1akp
30.09.2007, 19:53
Hi Leute,

hoffentlich nerve ich nicht, mit meinen dauernden Fragen.
Ich arbeite an einem Hausbussystem.
Bin schon bei den ersten Tests.

Nun möchte ich ein Menü in mein Prog einbringen und habe da einen Codeschnipsel gefunden. Nur blicke ich nicht so ganz durch...

Vielleicht kann mir ein Profi unter Euch den entscheidenen Tip geben?

Solang ich keine Taste drücke, bleibt das Display ohne ANzeige und das Prog im Schleife zur Tastenabfrage. Das Menü funktioniert super, nur ich komm nicht wieder raus in den Urzustand, wo ich in der Schleife bin und das Display mir wieder zur Verfügung steht.

Habe auch den Simulator benutzt, aber ich komm nicht weiter...

Ich möchte ein normales Hauptprogramm haben, wo bei Tastendruck in das Menü gesprungen wird. Wenn ich im Hauptmenü die Taste Menüzurück drücke, dann soll diese Schleife verlassen, das Display gelöscht, und ins Hauptprogramm zurück gekehrt werden.

Kann mir mal jemand auf die Sprünge helfen?
$sim
$regfile = "m32def.dat" 'Für ATMega 32
$crystal = 14745000 '14 MHz-Quarz
$baud = 9600
$hwstack = 128
$swstack = 40
$framesize = 80

'wenn Zeichen über RS485 empfangen, dann Interruptprogramm "Empfangen" anspringen
'On Urxc Empfangen 'UART Interrupt bei Zeichen empfangen
'Enable Urxc 'UART Interrupt einschalten
'Enable Interrupts 'Interrupts global ein

Ddra = &B00110000
Ddrb = &B00000000 '1=output ; 0=input
Ddrd = &B11000000

'*********** Belegung der Ein- und Ausgänge ********************
'
'PA0 bis PA3 Ein- oder Ausgänge anal. oder dig.
'PA4 Buzzer
'PA5 LED für Anzeigezwecke
'PA6 SDA I2C
'PA7 SCL I2C
'PB0 bis PB7 8 Taster oder Tasten mit Inkrementalgeber
'PC2 bis PC7 LCD-Anzeige
'PD0 RXD
'PD1 TXD
'PD2 1wire-Sensor
'PD4 DCF-77 Eingang
'PD6 RS485 RX-TX-Umschaltung
'PD7 RS485-RS232-Umschaltung


Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
Cursor Off ' Cursor ausschalten
Cls 'löschen display


Dim Menuepunkt As Byte
Menuepunkt = 2
Dim Menuevor As Byte
Menuevor = 2
Dim Menuezurueck As Byte
Menuezurueck = 2
Dim Menuehoch As Byte
Menuehoch = 2
Dim Menuerunter As Byte
Menuerunter = 2
Dim Menuecase As Byte
Dim Taste As Byte
Dim Schonbearbeitet As Bit
Declare Sub Menueupdate(submenupunkt As Byte , Submenucase As Byte , Submenuvor As Byte , Submenuzurueck As Byte , Submenuhoch As Byte , Submenurunter As Byte )

Tastehoch Alias Pinb.0 'hier definiert ihr die tastenpins
Tasterunter Alias Pinb.1
Tastelinks Alias Pinb.3
Tasterechts Alias Pinb.2
Taster1 Alias Pinb.7
Led Alias Porta.5

'Initialisierung und Löschen evtl. Variablen
Schonbearbeitet = 0
Taste = 0

Led = 1 'led anschalten

Startzeile:
If Tastehoch = 0 Then
Waitms 10 'wegen Tastenprellen
Taste = 1
Goto Testen
End If
If Tasterunter = 0 Then
Waitms 10
Taste = 2
Goto Testen
End If
If Tastelinks = 0 Then
Waitms 10
Taste = 3
Goto Testen
End If
If Tasterechts = 0 Then
Waitms 10
Taste = 4
Goto Testen
End If
Taste = 0
Schonbearbeitet = 0
Goto Startzeile

Testen:
If Schonbearbeitet = 0 Then Goto Neumenu
Goto Startzeile

Neumenu:
Schonbearbeitet = 1
Select Case Taste
Case 1 : Menuepunkt = Menuehoch 'je nach taste wird der neue menue-punkt gesetzt
Case 2 : Menuepunkt = Menuerunter
Case 3 : Menuepunkt = Menuezurueck
Case 4 : Goto Caseauswertung
End Select

Menueupdaten:
Call Menueupdate(menuepunkt , Menuecase , Menuevor , Menuezurueck , Menuehoch , Menuerunter) 'menue wird erneuert
Menueende:

Goto Startzeile

Caseauswertung:
If Menuecase = 0 Then
Menuepunkt = Menuevor
Goto Menueupdaten
End If
Cls
Menuepunkt = 2
Menuehoch = 2
Menuerunter = 2
Menuevor = 2
Menuezurueck = 2
'Select Case Menuecase 'hier kann die auswertung der ereignisse erfolgen
'Case 1 :goto .. 'vor rückkehr zur tasten abfrage muß menuecase wieder auf 0
'case 2 :goto ... 'gesetzt werden
'case 3 :goto ...
'End Select

'Locate 2 , 1 'dies dient nur zum test
'Lcd "Ereigniss " ; Menuecase ' ""
Menuecase = 0
Goto Menueende

Sub Menueupdate(submenupunkt As Byte , Submenucase As Byte , Submenuvor As Byte , Submenuzurueck As Byte , Submenuhoch As Byte , Submenurunter As Byte ) 'sub zum erneuern des menues
Cls
Local Beendet As Byte
Local Zahler As Byte
Local Kurzstring As String * 4
Local Langstring As String * 20
Local Zeile1 As Byte

Menurunter:
Submenupunkt = Submenupunkt + 2 'text und menuepunkt für taste runter-blättern wird gesucht und ausgegeben
Kurzstring = Lookupstr(submenupunkt , Menue)
Kurzstring = Left(kurzstring , 1)
If Kurzstring = "#" Then
Locate 4 , 1
Lcd "********************"
Submenupunkt = Submenupunkt - 2
Submenurunter = Submenupunkt
Else
Submenurunter = Submenupunkt
Langstring = Lookupstr(submenupunkt , Menue)
Locate 4 , 1
Lcd Langstring
Submenupunkt = Submenupunkt - 2
End If

Aktuell: 'text für aktuellen menuepunkt wird ausgegeben
Langstring = Lookupstr(submenupunkt , Menue)
Locate 3 , 1
Lcd Chr(126) ; Langstring

Menuevor:
Submenupunkt = Submenupunkt + 1 'text und menuepunkt für taste vor (rechts) wird gesucht und ausgegeben
Kurzstring = Lookupstr(submenupunkt , Menue)
Langstring = Left(kurzstring , 1)

If Langstring = "!" Then
Langstring = Right(kurzstring , 2)
Submenucase = Val(langstring)
Submenupunkt = Submenupunkt - 1
Goto Menuehoch
End If
Submenucase = 0
Kurzstring = "#" + Kurzstring
Zahler = 0
Beendet = 0
Do
Incr Zahler
Langstring = Lookupstr(zahler , Menue)
If Kurzstring = Langstring Then Beendet = 1
Loop Until Beendet = 1
Zahler = Zahler + 2
Submenuvor = Zahler
Submenupunkt = Submenupunkt - 1

Menuehoch: 'text und menuepunkt für taste hoch-blättern wird gesucht und ausgegeben
Submenupunkt = Submenupunkt - 2
Langstring = Lookupstr(submenupunkt , Menue)
Kurzstring = Left(langstring , 1)
If Kurzstring = "#" Then
Locate 2 , 1
Lcd "********************"
Submenupunkt = Submenupunkt + 2
Submenuhoch = Submenupunkt
Else
Submenuhoch = Submenupunkt
Langstring = Lookupstr(submenupunkt , Menue)
Locate 2 , 1
Lcd Langstring
Submenupunkt = Submenupunkt + 2
End If

Menuezuruck:
Beendet = 0 'text und menuepunkt für taste zurueck (links) wird gesucht und ausgegeben
Zahler = 0
Do
Decr Submenupunkt
Langstring = Lookupstr(submenupunkt , Menue)
Kurzstring = Left(langstring , 1)
If Kurzstring = "#" Then Beendet = 1
Loop Until Beendet = 1
If Submenupunkt = 0 Then
Zeile1 = 1
Else
Zeile1 = 0
End If
Submenupunkt = Submenupunkt + 1
Langstring = Lookupstr(submenupunkt , Menue)
Kurzstring = Left(langstring , 2)
Kurzstring = "#" + Kurzstring
Beendet = 0
Zahler = 0
Do
Langstring = Lookupstr(zahler , Menue)
If Langstring = Kurzstring Then
Beendet = 1
Else
Incr Zahler
End If
Loop Until Beendet = 1
Kurzstring = Lookupstr(submenupunkt , Menue)
Kurzstring = Right(kurzstring , 1)
Submenupunkt = Val(kurzstring)
Submenupunkt = Submenupunkt * 2
Submenuzurueck = Zahler + Submenupunkt
If Submenuzurueck = 2 Then
If Zeile1 = 1 Then
Locate 1 , 5
Lcd "Hauptmenue"
Zeile1 = 0
Else
Langstring = Lookupstr(submenuzurueck , Menue)
Locate 1 , 5
Lcd Langstring
End If
Else
Langstring = Lookupstr(submenuzurueck , Menue)
Locate 1 , 5
Lcd Langstring
End If


End Sub

' hinter der # steht die menueebene dahinter steht die rücksprungadresse für diese menueebene
' zB wird aus einem eintrag der ebene #04 (zB Abstand) in die ebene #3 eintrag 1 gesprungen (031) in diesem fall nach eingänge
' und von dort gehts zurück in ebene 1 eintrag 2 (012) das wäre dann "Tests"
'nach der rücksprungadresse folgt der erste menuepunt (max 20 Zeichen)und danach dessen vorprung adresse
'zB hinter "Einstellungen" steht 07 also verzweigt das menue von dort in die unter-ebene 7
'falls aus einem Menuepunkt nicht weiter in ein Untermenue gesprungen werden soll sondern ein bestimmdes Ereigniss stattfinden soll
'dann kommt als vor-sprung-adresse (die zahl hinter dem eintrag) ein ! und eine Zahl von 1-99 diese Zahl wird dann in der variable menuecase zurueckgegeben
'zB wenn man im Menuepunkt "Akku Laden" die menue-vor taste drückt wird der wert 02 zurueckgegeben diese können dann ausgewertet werden

Menue:
Data "#01" , "011" , "Sauna" , "02" , "Pool" , "05" , "Garage" , "09"
Data "#02" , "011" , "Licht innen" , "03" , "Licht aussen" , "04" , "Fertig-Signal" , "!05"
Data "#03" , "021" , "an" , "!01" , "aus" , "!02"
Data "#04" , "022" , "an" , "!06" , "aus" , "!07"
Data "#05" , "012" , "Pool-Licht" , "06" , "Solarheizung" , "07" , "Reinigungsmodus" , "08"
Data "#06" , "051" , "an" , "!08" , "aus" , "!09"
Data "#07" , "052" , "freigeben" , "!10" , "sperren" , "!11"
Data "#08" , "053" , "Pool reinigen" , "!12" , "Normalbetrieb" , "!12"
Data "#09" , "013" , "Licht" , "10"
Data "#10" , "091" , "an" , "!14" , "aus" , "!15"
Data "#EO" 'muß am ende stehen


Danke fürs anschauen.
Andreas

Jaecko
01.10.2007, 16:06
Also ohne jetzt genau dein Programm zu kennen, verwende ich bei den Menüs folgende Technik:

Benötigt werden 3 Variablen:
Mlv (String, z.B. Länge 20)
PressedKey (String mit Länge 1)
MString (String mit Länge Mlv + Pressedkey, z.B. 21)

Im String Mlv (Menulevel) wird der aktuelle Menüpunkt gespeichert (z.B. "Main" für das Hauptdisplay, "Settings1" für Einstellungen 1. Ebene, "SetTimeDate" für Datum/Zeit-Einstellungen etc);

In PressedKey wird die gedrückte Taste gespeichert; also "U" für hoch, "D" für Runter, "M" Menü, "X" Escape/Exit... sowie "N" für keine
Taste.

Die beiden werden dann zu einem String MString vereinigt, dass der normalzustand z.B. "MainN" ist (also einfaches MString = Mlv + PressedKey). Wird eine Taste gedrückt (z.B. Menü "M"), ändert sich der String nach "MainM", wobei entsprechend dann reagiert wird.

In nem grossen Select-Case-Block werden dann alle möglichen Kombinationen abgefragt..

z.B.
Case "MainN": Anzeigen des Haupt-Display
Case "MainX": würde System abschalten
Case "MainM": ruft Menü auf
Case "Settings1X": springt von den Einstellungen zurück (z.B. nach Main)
Case "VolumeU": dreht Lautstärke hoch
...


Die Daten sind bei mir dann so angeordnet, dass bei "....N" (also keine Taste gedrückt) nur LCD-Ausgaben erfolgen und bei allen anderen Tasten
entsprechend reagiert wird.
Vorteil hier: man sieht gleich ohne Kommentare, was der jeweilige Case macht; Nachteil: Speicher wird mit den 3 Variablen belegt; aber sollte eh genug da sein.

Nach dem Case-Select-Block bzw. bei der Tastenauswertung muss die gedrückte Taste natürlich wieder auf "N" gesetzt werden.

Etwas kompliziert, aber so klappts bei mir mit den Menüs problemlos.


Hier ein Beispiel-Ausschnitt aus nem Programm von mir:
(Die Gedrückte Taste wurde hier mit mehr als nur 1 Zeichen angegeben; ein ! soll das als Befehl kennzeichnen)



'Ausschnitt aus dem Bereich der Tastenabfrage
'(Tasten bei mir per Widerstandsmatrix an einem ADC angeschlossen)

Adcval0 = Getadc(0)
If Adcval0 < 15 Then 'Keine Taste gedrückt
Key = "!NON"
End If

If Adcval0 > 14 Then Waitms 25
Key = Getkey() 'GetKey() besorgt sich aus der anliegenden Spannung die gedrückte Taste

'Umschreiben der Tasten:
If key = "E" then Key = "!ENT"
If key = "X" then Key = "!ESC"
If key = "C" then Key = "!F12"
If key = "U" then Key = "!UP"
If key = "D" then Key = "!DWN"
If key = "L" then Key = "!LFT"
If key = "R" then Key = "!RIG"


'Ausschnitt aus Bereich: Datum einstellen: Jahr gewählt


Case "SetDateY!NON" 'Zeit prüfen, Timer stoppen und Zeit anzeigen
Checktime
Stop Timer1
Lcd1 = "<Set Date>"
Lcd3 = " " + Strdate
Lcd4 = " " + Chr(1)

Case "SetDateY!RIG" : Mlv = "SetDateM" 'Zum Monat wechseln
Case "SetDateY!UP" : Incr Tyear 'Jahr erhöhen
Case "SetDateY!DWN" : Decr Tyear 'Jahr erniedrigen
Case "SetDateY!ENT" 'Jahr übernehmen und vorher gestoppten Timer neu starten
Mlv = "TimeDate2"
Start Timer1
Case "SetDateY!ESC" : Mlv = "TimeDate2" 'Zurück zu den Zeiteinstellungen

dl1akp
01.10.2007, 18:20
Hallo Jaecko,

danke für Deine Antwort. Geht ganz anders an das Problem rein wie meine Variante (die nicht von mir ist, ich habe den Codeschnipsel gefunden und kenne den Autor nicht mehr. Nur das er "Daniel" heist).

Habe aber jetzt mit Hilfe des Simulators und meheren Versuchen in der realen Schaltung die Funktion rausgefunden.
Ich weis also jetzt wie es geht, und komme weiter mit meinem Proggi..

Danke, vielleicht kann ja jemand mit den Menü-Ideen auch was anfangen...

Andreas

kalletronic
18.11.2007, 14:41
Hi Andreas,

klingt interessant, könntest du vielleicht etwas mehr von deinem Hausbus erzählen? Ich hab mir auch mal ein paar Überlegungen dazu gemacht, hab sie aber wieder verworfen, da nie was gescheites rausgekommen is

Mfg
Kalle