Hallo an alle!
Hat irgendjemand von euch schon mal ein Menu für ein LCD realisiert?
Über drei Tasten steuerbar über 2 tasten (gleichzeitig) ins Menu.
1 Taste hoch. 1 Taste runter. 1 bestätigen.
Mir geht eigentlich nicht darum wie man es tun sollte sondern wie es am
sinnvollsten wäre es zu implementieren?
Danke
Gruß
Andreas
Das macht man am besten objektorientiert (also in C++) Eine Klasse für
einen Menueintrag und eine Klasse für ein Menu. Das ganze kann man dan
beliebig kombinieren und erweitern. In C shreibste dich damit tot.
Z.B. so (muss natürlich noch für dein µC angepasst werden):
cout und cin musste durch lcd-output und schalter-abfrage ersetztn.
Ich weiß nicht wie weit die C++ lib ist. vielliecht musste noch ne
kleine vector- und string-klasse schreiben; das geht aber schnell.
Hi,
habe sowas mal in der Firma realisiert. Natürlich in C.
das ganze läuft eventorientiert. Jedes tastedrücken erzeugt ein event.
natürlich muss man sich immer merken in welchem menü man sich grade
befindet. über geschachtelte case anweisung kann dann der tastendruck
und die aktuelle ausgabe realisiert werden.
unten nur eine grobe skizze:
CASE TASTE1
case menu1:
funktion A
set aktives menu2
case menu1:
funktion B
set aktives menu3
case menu1:
funktion C
set aktives menu4
CASE TASTE2
case menu3:
funktion D
set aktives menu3
case menu4:
funktion E
set aktives menu4
CASE TASTE3
case menu2:
funktion F
set aktives menu3
Der aufgezeigte C++-Ansatz ist fuer kleine Mikroconroller nicht gut
geeignet. Switch/Case-Ketten koennen bei Erweiterungen unuebersichtlich
werden. Ein Ansatz wie er z. B. im Projekt "tinymenu" (avrfreak.net
academy user-projects) ersichtlich wird, erscheint mir zumindest
brauchbarer.
@c++'lerin
"In C shreibste dich damit tot."
Aber ganz im Gegenteil !
Du legst einfach ne Struktur an, die aus dem Text und dem
dazugehörenden Funktionspointer besteht.
Dann einfach damit eine Tabelle schreiben, die alles enthält.
Und dann einfach den Index mit den Tasten hoch und runter zählen, den
Text anzeigen und die Funktion aufrufen.
Als maximalen Index nimmt man per sizeof(table)/sizeof(structur) die
Anzahl Elemente in der Tabelle oder legt einen letzten Eintrag fest
(Null-Text, Null-pointer).
D.h. man kann ganz easy weitere Punkte hinzufügen oder welche löschen.
Und für Untermenüs muß man nur weitere Tabellen anlegen, die
Auswahlfunktion kann die gleiche bleiben (rekursiver Aufruf).
Sieht übersichtlich aus und ist einfach zu erweitern.
Das wird vor allem nicht so ein ellenlanges Case-Monster wie dieses C++
Beispiel.
Und solche manuellen Zählungen (entry10..entry40) werden schnell
unübersichtlich und fehleranfällig in größeren Programmen (wie war
nochmal der letzte bisher vergebene entry ?).
Ich arbeite gerne mit Tabellen, das ist kompakt und Code sparend.
Peter
Auch in AVR-ASM geht das gut mit Tabellen.
Die Ausgaberoutine braucht Basisadresse (Tabellenanfang) und
Menüpunktnummer. Der Aufruf der Menüpunkte erfolgt nach Auswertung der
(im Timer-Interrupt entprellten) Tasten mittels ijmp über Z-Pointer.
...
@Peter
@HanneS
Könntest Ihr ein kleines Beispiel als Codfragment hier Posten!
Ich könnte den Ansatz demnächst brauchen.
Vielen Dank im Vorraus!
Gruß
Klaus
Vielen Dank für eure regen Antworten.
Peter seine Variante klingt sehr vielversprechend und sinnvoll.
Danke Peter.
Werde das mal umsetzen, natürlich nicht mehr heute.
Es ist ja nu auch Schlafenszeit.
Andreas
Habe eben noch einen Fehler im Hauptprogramm entdeckt und beseitigt:
TIM0_OVF: ;Timer0 Overflow Handler
in srsk,sreg ;SREG sichern
sbr flags,1<<lcdtakt ;Timer0 Überlauf: LCD_Out freigeben
out sreg,srsk ;SREG wiederherstellen
reti ;
Hatte ich bisher übersehen...
...
Hallo,
... der Thread ist zwar schon ein paar Tage alt, aber ich hoffe, er
wird noch gelesen.
@...HanneS... : Da ich auch noch ein paar 8x24-er LCDs rumliegen habe,
kamen mir die Routinen (s.o.) sehr gelegen.
Jedoch scheint in dem Locate x,y-Macro ein kleiner Fehler zu sein:
Im RAM-Ringpuffer werden doch vor dem eigentlichen auszugebenen
Zeichern die DD-Ram-Addr. des LCD hinterlegt. Bei mir ergibt sich
jedoch folgende Zuordnung:
Locate 0,0 -> Addr.0x00 lt. Datenblatt Zeile 0
Locate 1,0 -> Addr.0x30 lt. Datenblatt Zeile 2
Locate 2,0 -> Addr.0x60 lt. Datenblatt Zeile 4
Locate 3,0 -> Addr.0x90 lt. Datenblatt Zeile 6
Locate 4,0 -> Addr.0x18 lt. Datenblatt Zeile 1
Locate 5,0 -> Addr.0x48 lt. Datenblatt Zeile 3
Locate 6,0 -> Addr.0x78 lt. Datenblatt Zeile 5
Locate 7,0 -> Addr.0xA8 lt. Datenblatt Zeile 7
Ich habe es bisher nur trocken durchpropiert, jedoch nicht getestet.
Hab ich irgendwo nen Denkfehler??
Gruß Rudi
Es gibt vermutlich verschiedene Versionen dieses Displays. Das
Datenblatt, welches ich von Pollin habe, stimmt nicht mit der Realität
meiner Displays überein. Siehe Anhang (Datenblattauszug): mein Display
(und daher auch mein Locate) hat die Aufteilung, die links mit
Bleistift nachgetragen wurde.
Falls deine Displays anders organisiert sind, dann musst du Locate an
deine Displays anpassen. Wenn du anhand meiner Aufteilung den Algo
ermittelt hast, dürfte das kein Problem sein.
Viel Spaß...
Übrigens lässt sich das noch vereinfachen. Wenn man das LCD nur bei der
ersten Initialisierung löscht, während des Normalbetriebs auf das
Löschen verzichtet und stattdessen Leerzeichen schreibt, dann genügt
immer die kurze "Wartezeit", da nur LCD-Clear die lange Wartezeit
benötigt. Man kann sich also das Umschalten des Timers sparen oder das
Ausgabeflag gleich nebenbei von einem anderen, sowiso laufenden Timer
zyklisch setzen.
Das Löschen per Leerzeichen wäre dann:
locate 0,0 ;erste Zeile, erste Spalte
print 32,192 ;192 Leerzeichen schreiben
Berichte mal, was draus geworden ist...
Bit- & Bytebruch, guten Rutsch...
...
Dies (Anhang) war ein Test mit meinem Locate. Da dazu mal schnell ein
Programm für das 4x27 (aber mit 8x24-Treiber, noch ohne Ringbuffer)
missbraucht wurde, stehen da noch ein paar andere Sachen auf dem
Display, auf die es aber hier nicht ankam.
...
So ist das, wenn man sich auf Datenblätter verlässt - man ist verlassen
!!!
Getestet habe ich, wie schon erwähnt, die Displays nur kurz mit div.
Par-Port-Programmen, jedoch nicht mit dem ATMegaxx. Nur so als
Fkt.-Test, ohne mir über die Zeilenaddressierung klar zu sein.
Nun aber im aktuellen Projekt spielt das sehr wohl eine Rolle.
Danke auch für den Tip, der Vereinfachung. Sicher weniger
Programmieraufwand, aber zeitintensiver 192 Byte * 20µsec = 3,84
msec(gegenüber 1,25 msec beim ClearHome-Befehl), bevor alles gelöscht
ist. Aber einfacher - werde ich mal testen.
Im nächsten Jahr werde ich das mal testen ;-)
Bis dahin und Guten Rutsch
Rudi
PS: @...HanneS...
Werde die Raketen noch manuell zünden, obwohl das Zünduhr-Pgm. dafür
bestensgeeignet wäre !!
Man muss ja das Display nicht löschen, wenn man darauf achtet, dass man
immer volle Zeilen schreibt und denzufolge alle vorherigen Zeichen
überschreibt. Im Zünduhr-Programm wird das Display nur beim Init
gelöscht.
Ich zünde übrigens garkeine Raketen mehr, das muss ich nicht unbedingt
haben. In meiner Jugend habe ich genug Knallzeugs gebaut und gezündet
(ohne dass es jemals "eng" wurde), da kann ich inzwischen gut drauf
verzichten.
Die Zünduhr kommt aber heute Nacht zum Einsatz (mit einem
"Verteiler"), die habe ich nämlich nicht für mich gebaut, sondern für
einen Nachbarn, der vor einigen Monaten seine Pyrotechnik-Ausbildung
abschloss und nun offiziell Feuerwerke Klasse 4 abbrennen darf.
Das wird heute der zweite Einsatz, aber erstmalig mit "Verteiler"
(weiteres von der Uhr über Draht seriell gesteuertes Zündgerät für 31
Zündkreise). Geplant ist später der Einsatz von Zünduhr (16 Kanäle) mit
2 Verteilern (je 31 Kanäle). Das System lässt sich bis zu 6 Verteiler
ausbauen, wobei es für Zündbefehle noch den "logischen" Verteiler 7
(H) gibt, auf den Verteiler 1 und 2 (B und C) synchron reagieren. Das
ermöglicht Synchronzündungen auf beiden Seiten.
Der erste Einsatz (nur Hauptgerät mit 16 Zündkreisen) vor einigen
Wochen hat dem "Betreiber" schon die Finger gerettet. Zwei für
Luntenzündung zugelassene Vulkane (vom deutschen Fachhandel)
detonierten ohne Verzögerung. Bei Luntenzündung wär das peinlich
geworden.
An der PC-Software muss ich noch etwas basteln. Aber erstmal sehen, was
der "Betreiber" da für Wünsche äußert. Bis jetzt ist neben
Schusslistentausch mit der Uhr nur das Erstellen, Editieren und
Laden/Speichern der Schusslisten vorgesehen. Eine "Simulation" wäre
noch interessant, aber leider stimmen die vom Hersteller angegebenen
Abbrennzeiten von Batterien und Vulkanen selten mit der Realität
überein. Aber irgendeine Art Simulation muss noch rein, um im Vorfeld
die Musiksynchronität austesten zu können.
Guten Rutsch... - Und passt beim Knallen auf Eure Finger auf!!!
...
@Hannes: Was für ein Datenblatt hast Du denn von Pollin bekommen?
Ich hab Bestell-Nr. 120387 gekauft (4 Zeilen, 1xM50530 und 1xM50521)
und weder Datenblatt dazubekommen noch ist ein Download verfügbar.
Nciht mal die Belegung der 15 Pins ist nachvollziehbar.
Das von Dir genannte LCD (120387) habe und kenne ich nicht, das gibt es
vermutlich auch noch nicht lange.
Ich hatte vor langer Zeit mal ein 8x24 mit Controller M50530 und bekam
über Ebay etliche von dieser Sorte nachgekauft (gebraucht, aus
Zerlegung von Telefonen). Die sind zwar teils leicht zerkratzt, aber
ich mache ja keine Produktion für den Verkauf.
Woher das Datenblatt zum M50530 stammt, kann ich jetzt gar nicht sagen.
Ich hänge es mal mit an, vielleicht hilft es Dir oder jemand Anderen ja
weiter.
...
@ peter dannegger
Du hast oben von einer Menüstruktur gesprochen, die als Tabelle angelegt
ist und in Untermenüs verzweigen kann. Eine flache Menüstruktur ist klar
- da gibt es nur einen Menüindex. Wie erweitert man diese
Tabelle/Struktur nun um Untermenüs? Wie verwaltet man dann die jeden
Index der Unter- und Untermenüs??
Bitte ein kleines Programm anfügen.
Danke, MiGu.