mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [AVR-ATmega8] LCD-Menü mit 2 Tastern


Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Gemeinde!

In der Schule habe ich ein Abschlussprojekt zugewiesen bekommen, in dem 
ich IC´s testen und simulieren muss. Als Hardware habe ich vom Lehrer 
das MyAVR-Board MK2 USB mit dem ATMenga8 und das MyAVR-LCD V2.4 (2x16) 
bekommen.

Um die verschiedenen IC´s testen/simulieren zu können wollte ich ein 
Menü realisieren, in dem man            1. IC´s testen
                                        2. IC´s simulieren
wählen kann.

Leider weiß ich nicht genau, wie ich den uC programmieren muss, damit er 
bei einem Tastendruck in´s nächste Menü kommt.

Ich hoffe ich konnte mein Problem gut beschreiben.

Auf gute Antworten freue ich mich schon =)

mfg theo-rettisch

Autor: Anselm 68 (anselm68)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schluck
Welche IC´s sollst du testen?

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Standard IC´s...

And
Or
Not
Nand
Nor

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
erstmal .. hinsetzen und überlegen
dann überlegen programmiersprache ..

dazu hier :
http://www.mikrocontroller.net/articles/AVR-Tutorial
oder
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

dann lernen wie man das LCD ansteuert und dort texte draufschreibt
und man sollte wissen WAS da passiert  !!!!
dann kannst du dir gedanken über ein menü machen


am sinnvollsten ist ein array von menüeinträgen

array[i] = { eintrag 1 , eintrag 2 , ...., eintrag n };

ein zeiger zeigt dann auf den eintrag der angezeigt werden soll
oder eine globale variable  array[ zeiger ]

nun das ganze in dem array kombinieren
also im array steht der text , eine stelle wo das menü hingehört  und 
eine funktion dahinter

da man nun weiß an welcher stelle im array man ist
kann an die entsprechende aktion dahinter recht einfach aufrufen

um zu navigierien must du die taster abfragen
ob diese eben gedrückt wurden , oder nicht

und dann entsprechend reagieren



wenn du lange genug suchst , findest du hier un da teile die du 
verwenden könntest

ich wage aber anzuzweifent das du das alles kombinieren kannst

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Huhu...


das LCD ansteuern klappt ja....
Das mit den Arrays auch...
Nur dass er den nächsten Text auf das LCD schreibt, wenn ich einen 
Taster gedrückt hatte, klappt nicht...

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann denk mal drüber nach wenn du einen taster drückst und er das merkt
bzw das dein programm ja immer rasend schnell eine schleife durchläuft

daraufhin must du irgendwas tun und den text neu schreiben auf dem LCD


wie man taster bzw eingänge abfragt steht auch im tut

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HiHo..

Also irgendwie.....
Ich weiß nicht..
Alles was ich versuche klappt nicht....

Mag mir vllt jmnd. das kleine Stück Quellcode schreiben?
Oder besser gesagt genauer erklären?

Ich erkläre mal genau, wies ablaufen soll:

Programmstart...Erste Zeile:    1. IC´s testen
                                2. IC´s simulieren

Nach Tastendruck (bsp. PB5):    1. IC´s testen
                                - AND

Nach Tastendruck (bsp. PB6):    1. IC´s testen
                                - OR

Nach Tastendruck (bsp. PB5):    IC: OR
                                Bits senden...

PB5 soll also "OK" und PB6 "Weiter" darstellen...

So ungefähr dachte ich es...aber er reagiert NIE auf einen Tastendruck 
:/

mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehe ich es richtig, dass das Problem nicht das Menu ist, sondern, dass 
ein Tastendruck nicht erkannt wird?

Grüße,

Peter

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man so sagen...

Hatte mich am Anfang wohl etwas falsch ausgedrückt. `Tschuldigung..

mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was läuft denn schon alles?
Kannst du den Code posten?


edit:
Ein Schaltplan wäre auch praktisch...


Peter

Autor: Theo Rettisch (theo-rettisch)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Was läuft ist:

LCD Ausgabe

Mehr aber auch nicht, da er ja keinen Tastendruck "erkennt".

Theoretisch bin ich natürlich schon wieter...


mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also verwendest du Taster 1 und Taster 2, die beide auf dem Mainboard 
sind. Und das Display ist das, was im MyAVR Shop dazu passend verkauft 
wird.

Das macht ja zumindest Fehler in der Hardware unwahrscheinlich.

Es wäre natürlich trotzdem hilfreich, wenn du mal das posten könntest, 
was du bisher programmiert hast, sonst kann dir hier niemand helfen.

Welchen Compiler verwendest du?
Ich hab die Verkaufsseite von MyAVR nur gerade überflogen und gesehen, 
dass es eine eigene IDE gibt für verschiedene Programmiersprachen und 
wohl auch eigene Bibliotheken.

Als einfache Übung könntest du etwas programmieren, das nur eine 
Leuchtdiode einschaltet, wenn das Programm startet.
Als nächste Übung wäre es sinnvoll, die Leuchtdiode erst einzuschalten, 
wenn ein Taster gedrückt worden ist.
Damit wäre die Funktionalität der Taster und entsprechende 
Bibliotheksverwendung überprüft.

Peter

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der sinn dahinter  ist einfach das dir keiner hier arbeit abnimmt weil 
du faul bist diese eigenständig zu erledigen

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende den AVR-Studio..

Der momentane Code:
#include <avr/io.h>
#define F_CPU 3686400UL    

#include "myavr_lcd.h"     
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>

const char haupt[] PROGMEM= "Hauptmenue";
const char test[] PROGMEM= "1. IC testen    ";
const char sim[] PROGMEM= "2. IC simulieren ";

int main()
{
  lcd_init(LCD_DISP_ON);    

  
    lcd_puts_p(haupt);  

    lcd_gotoxy(0,1);    
    lcd_puts_p(test);  

  if ((PINB&0b00010000)==1)
  {
    lcd_puts_p(haupt);  

      lcd_gotoxy(0,1);    
      lcd_puts_p(test);
  }

    while(1)
    {

    }

    return 0;
}


mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und du bist sicher, dass der Taster an Pin B5 angeschlossen ist?
Zieht er denn nach Vcc oder nach Gnd?
Das entscheidet ja darüber ob du auf ==1 oder ==0 abfragen musst.

Dann solltest du noch den Pullup einschalten, bevor du den Taster 
benutzt:
PORTB |=0b00010000;

Peter

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und ich sehe noch etwas:

Die Endlosschleife ist leer, die Tasterabfrage passiert nur einmal 
davor. Das heißt, der Taster müsste gerade in dem Moment des 
Programmstarts gedrückt sein, damit etwas passiert.

Wird denn der Testtext angezeigt?

Peter

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den internen PullUp hab ich nun eingeschaltet...

(Er zieht nach Vcc)

Und trotzdem passiert nun nichts...

|0-0-0-1-0-0-0-0|
-----------------
|7-6-5-4-3-2-1-0|

Das heißt doch, dass er an Pin 5 ist, oder nicht?...

Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probiers mal so:
#include <avr/io.h>
#define F_CPU 3686400UL    

#include "myavr_lcd.h"     
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>

const char haupt[] PROGMEM= "Hauptmenue";
const char test[] PROGMEM= "1. IC testen    ";
const char sim[] PROGMEM= "2. IC simulieren ";

int main()
{
  lcd_init(LCD_DISP_ON);    
  PORTB |=0b00010000;

  
    lcd_puts_p(haupt);  

    lcd_gotoxy(0,1);    
    lcd_puts_p(test);  

    while(1)
    {
      if ((PINB&0b00010000)==0)
      {
        lcd_puts_p(haupt);  
        lcd_gotoxy(0,1);    
        lcd_puts_p(test);
        while(1);
      }
    }
    return 0;
}

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er wird von Anfang an angezeigt....

Meinst du ich soll die Tasterabfrage in eine Schleife einfügen?

edit: OK ich versuchs mal so

Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das heißt doch, dass er an Pin 5 ist, oder nicht?...

Ja.

Es ist aber doch nicht gesagt, dass das stimmt, oder steht das irgendwo 
so?
Aus dem Layout kann man nichts erkennen, weil es wohl mehr als 2 Layer 
sein müssen, die nicht alle dargestellt sind. Ansonsten sieht es nämlich 
so aus, als wäre der Taster nicht angeschlossen.

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darf ich sagen, dass du ein schatz bist? =D

Nun kommt die zweite auswahl zum Vorschein...danke dir erstmal ;)

Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wenn er nun nach einem weiteren Tastendruck wieder "IC testen" 
anzteigen soll, muss ich dich folgendes schreiben, oder nicht? :
main:

    lcd_puts_p(haupt);  
    lcd_gotoxy(0,1);    
    lcd_puts_p(test); 

while(1)
{
    if ((PINB&0b00010000)==0)
    {
      lcd_puts_p(haupt);  
      lcd_gotoxy(0,1);    
      lcd_puts_p(sim);

      if((PINB&0b00010000)==0)
      {
        goto main;
      }

      while(1);
    }

}

mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt würde ich dir empfehlen mehr zum Thema Tasterentprellung und 
Statemachines zu lesen, das werden die nächsten beiden Probleme sein.

Ich teile meine Programme immer in mehrere Funktionsblöcke. Einer 
üblicherweise für das Userinterface (Display, Taster, Lampen...), einer 
für die Menunavigation, ein Echtzeitblock, der alles zeitkritische 
erledigt und dann jede Menge Funktionen, die den Rest machen.

Das sieht dann etwa so aus:
void display(int number)
{
  switch (number)
  {
    case 0:
      print(...);
    break;
    case 1: usw...
  }

}

interrupt timer...
{
  //hier der Echtzeitteil, z.B. Tasterentprellung
}

int main()
{
  int state = 0;
  init_everything(); //ist irgendwo definiert

  while(1)
  {
    switch(state)
    {
      case 0:
        display(0);
        state = 1;
      break;
      case 1:
      if (Taster1) 
      {
        state = 3;
        display(2);
      }
      break;
      usw.
    } 
  }
}

so lassen sich recht schnell aufwändige Menüs realisieren.

Peter

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Tipps, aber magst du mir vllt eben meine Frage 
beantworten?^^

mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit den goto Sprüngen ist ziemlich unübersichtlich, wenn man davon 
mehrere hat.
Deswegen verwendet goto so gut wie niemand und man empfiehlt es auch 
nicht weiter.

Der Code wird so auch nicht richtig funktionieren, weil ich da ein 
while(1); eingebaut habe, das an der entsprechenden Stelle eine 
Endlosschleife darstellt.

Versuch das am besten so zu strukturieren, wie ich es oben aufgezeigt 
habe.

Peter

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
statt
if((PINB&0b00010000)==0)

besser

if ( !(PINB & (1<<PB5)) )
{
}

verwenden ..

zudem must du die taster entprellen
entweder di fertigen routiene hier ausm forum verwenden
oder selbst was bauen nach schema F

if ( taste )
  {
    _warte 20ms();
   // solange taste gedrückt ist hier däumchen drehen
   while( taste ) ;
   // taste losgelassen
   aktion();
  }


Für dein Menü vewende am besten ein Array aus einer Menüstuktur.
In der Struktur steht dein Menütext bzw der Zeiger auf deinen Menütext,
der Funktionszeiger  was betätigt werden soll bei einer "Aktion()"
und vlt Kennungen , Ebenemerker oder sownstwas / nix.
Davon nun ein Array erstellen und als globale Variable ein menü_eintrag.
Das ist ein einfacher Zähler. Dieser wird bei jeder Betätigung der Taste 
hochgezählt, ist er am Ende der Einträge angekommen , rücksetzen auf 0 
und von vorn.

Wenn sich menü_eintrag geändert hat  !! sollte man üblicherweise auch 
mal das LCD neu beschreiben ...

Soweit sollte man das erstmal hinbekommen.
Dann steht schonmal immer nach jedem Tastendruck was anderes aufm LCD.


Wird die andere Taste gedrückt um die aktion auszuführen , hat man mit 
menü_eintrag die aktuelle Position und ruft aus der Struktur den 
Funktionszeiger auf.


dahinter verbrigt sich dann eine Funktion die eben testet oder simuliert

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Tip für bessere Lesbarkeit am Rande:

Das kommt ganz oben in den Code:
#define Taster1  !(PINB & (1<<PB5))

hilft enorm, man kann dann so abfragen:

if (Taster1)
usw..

Peter

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch ein Beispielcodeschnippsel zur Tasterentprellung mit 
Unterscheidung ob der Taster nur einmal pro Drücken ausgewertet werden 
soll oder immer solange gedrückt wird:

Beitrag "Re: Atmel Mega 8 verhält sich nicht wie in AVR Studio Simulation"

Peter

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs nun mit den Arrays soweit, dass ich zweischen -IC testen- und 
-IC simulieren- "switchen" kann...
Nur macht er es auch schon automatisch...er zeigt immer beide einträge 
ganz schnell hintereinander an..wie kann ich das umgehen?

Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem habe ich nun gelöst, indem ich einfach ein wenig warte 
(   _delay_ms(20)    )....nun gehts daran die einzelnen IC´s auswählen 
zu können...

mfg Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider bin ich noch nicht weiter...Denn ich weiß nicht wie ich in ein 
Sub-Menü einsteigen soll..wenn ich es mit switch-case versuche, bleibt 
er einfach "hängen"..


mfg Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur mal so nebenbei...

Ich habe grad gemerkt, dass wenn ich mein USB-Kabel aus dem Port ziehe, 
dass dann die Taster nicht mehr funktionieren...

Woran kann das liegen?


mfg Theo

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
versuche erstmal damit klarzukommen was deine aufgabe ist
dann immer im hinterkopf behalten das der µC IMMER eine hauptschleife 
durchrennt
und du bei aktionen eben etwas erreichen willst
mach dir dazu zeichungen  und ablaufpläne

für untermenüs gibts auch mehrere methoden
wenn du bei swich case  bleibst wird das schnell sehr groß
ebenso deine verwendung von lcd_puts( "...")  berballert mehr speciher 
als gewollt
konstanen IMMER im flash !!!  also const char text1 PROGMEM = ....
wenn es keine lcd_puts_P( .. ) gibt .. schreib dir eine die das macht

Autor: Theo Rettisch (theo-rettisch)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich packe den funktionierenden Quellcode mal als Anhang hier hinein.

Ich versuche nun schon seid ewigen Stunden ein Untermenü zu erstellen, 
aber er geht nur durch zufall in ein Untermenü. Nicht wenn ich drücke.


[c]
case 1:
 if(Tweiter)
 {
   _delay_ms(50);
   _delay_ms(50);
   while(Tweiter);

   display (0);
   menue = 2;
 }

 switch(submenue)
 {
   case 0:
    if(Tok)
    {
     display(1);
    }
    break;
 }

break;

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theo Rettisch schrieb:
> Ich packe den funktionierenden Quellcode mal als Anhang hier hinein.
>
> Ich versuche nun schon seid ewigen Stunden ein Untermenü zu erstellen,
> aber er geht nur durch zufall in ein Untermenü. Nicht wenn ich drücke.

Weil der ganze Ansatz scheisse ist.

Du holst dir jetzt erst mal von hier
http://www.mikrocontroller.net/articles/Entprellun...
die Routinen für die Tastenbehandlung und bringst die zum laufen.


Dein Programm könnte zb so aussehen

lcd_put_choice_p( uint8_t row, const char* text )
{
  lcd_gotoxy( row, 2 );
  lcd_puts_p( text );
}

void Menu1()
{
  uint8_t choice;

  lcd_clear();
  lcd_put_choice_p( 0, "AND" );
  lcd_put_choice_p( 1, "OR" );
  lcd_put_choice_p( 2, "Exit" );

  choice = 0;
  lcd_gotoxy( 0, 0 );
  lcd_putc( '>' );

  while( 1 ) {
    if( get_key_press( 1<<KEY0 ) ) {
      lcd_gotoxy( choice, 0 );
      lcd_putc( ' ' );
      choice++;
      if( choice == 3 )
        choice = 0;
      lcd_gotoxy( choice, 0 );
      lcd_putc( '>' );
    }

    if( get_key_press( 1<<KEY1 ) ) {
      if( choice == 0 )
        PerformAnd();

      else if( choice == 1 )
        PerformOr();

      else if( choice == 2 )
        break;       // ausbrechen aus der while Schleife
    }
  }
}

int main()
{
  ....

  while(1) {

   
    if( get_key_press( 1<<KEY0 ) )
      Menu1();

    else if( get_key_press( 1<<KEY1 )
      Menu2();
  }
 }

Du willst dir auch die Menüsteuerung nach Möglichkeit so organisieren, 
dass du die eigentliche Menübearbeitung nur einmal hast und die 
Menütexte zb in einem Array zusammenfasst.

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Magst du mir nicht lieber erklären warum er nicht so toll ist?

Weil mit "weil der ganze Ansatz scheiße ist" kann ich recht wenig 
anfangen.

Theo

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theo Rettisch schrieb:
> Magst du mir nicht lieber erklären warum er nicht so toll ist?
>
> Weil mit "weil der ganze Ansatz scheiße ist" kann ich recht wenig
> anfangen.

Weil du das Thema Tastenentprellung komplett ignorierst. Und mit dem

if ( !(PINB & (1<<PB5)) )

wirst du sowieso nicht glücklich werden, egal wie oft du das umformst. 
Du willst nämlich das Drücken einer Taste detektieren, also das 
Umschalten von 1 auf 0 und nicht ob die Taste gedrückt IST. Die Taste 
ist nämlich aus Prozessorsicht eine halbe Ewigkeit gedrückt und wenn er 
in 1 Sekunde diese If-Abfrage 120000 mal durchläuft, dann wird dein 
Programm 120000 mal in dieses If hineingehen.

Und für den Rest: Ich hab dir im vorhergehenden Posting mal skizziert, 
wie so etwas aussehen könnte. Wie du siehst, nimmt dir die Entprellung 
aus dem Link die ganze Arbeit der Tastenbehandlung ab. Du brauchst nur 
noch die Ergebnisse abholen.

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich aber nach einem Tastendruck eine gewisse Zeit warte, ist das 
doch auch ein "entprellen"....
Oder nicht?

Theo

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theo Rettisch schrieb:
> Wenn ich aber nach einem Tastendruck eine gewisse Zeit warte, ist das
> doch auch ein "entprellen"....
> Oder nicht?

Ich habe die Post erst gesehen, nachdem ich meine geschrieben habe.
Ja das stimmt schon. Trotzdem fährst du mit den verlinkten-Funktionen 
besser. Schon alleine, weil du nirgends ein delay drinnen hast. Die 
Funktion get_key_press liefert TRUE, wenn seit dem letzten Aufruf die 
angegebene Taste gedrückt wurde und managed alles andere. Du brauchst 
dich um nichts weiter kümmern. Damit hast du die Behandlung der Tasten 
aus dem Weg und kannst dich ganz darauf konzentrieren, wie deine Menüs 
funktionieren sollen :-) (zb das Scrollen mehrere Menüeinträge in einem 
2 (4?) - zeiligem Display, zb. wie der Benutzer sieht, welcher 
Menüeintrag jetzt gerade der aktive ist, zb ...)

Die Tastenfunktionalität konfigurieren nicht vergessen. Aber das sollte 
eh selbstverständlich sein.

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist ein zweizeiliges LCD mit 16 Spalten.

Theo

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theo Rettisch schrieb:
> Es ist ein zweizeiliges LCD mit 16 Spalten.

Na denn.

Tasten zum laufen bringen.
Und schon kannst du dir ein Konzept zurechtlegen, wie du 20 Menüeinträge 
mit einem 2-zeiligen LCD handhabst.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber zu deinem Code.

Ich denke, der Taster, der dich momentan interessiert ist an PB5?

Warum schaltest du dann hier

  PORTB |=0b00010000;

den Pullup für PB4 ein?

(Genau das ist der Grund, warum man die Schreibweise

     PORTB |= ( 1 << PB5 );

bevorzugt. Dann mancht man nämlich nicht so dumme Fehler und verzählt 
sich in der Position des 1 Bits)

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab nun die entprellung außenvor gelassen und mich damit 
beschäftigt, wie ich denn in ein Submenue komme...
case 1:
           if(Tweiter)
        {
          _delay_ms(50);
          _delay_ms(50);
          while(Tweiter);
        
          display (0);
          menue = 2;
        }

        switch(submenue)
        {
          case 0:
            if(Tok)
            {
              _delay_ms(50);
              _delay_ms(50);
              while(Tok);

              display(1);
              submenue = 1;
            }
          break;

          case 1:
            if(Tweiter)
            {
              _delay_ms(50);
              _delay_ms(50);
              while(Tweiter);

              display(2);
              submenue = 2;
            }
            break;
        }

        break;

Er geht dann nur ins Submenue wenn ich bei Menu case 1 den Tok 
drücke...ansonsten nicht...(und auch nur beim ersten mal)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theo Rettisch schrieb:
> Ich hab nun die entprellung außenvor gelassen

Es hindert Dich niemand daran, bewährte Lösungen zu ignorieren und 
selber was zu probieren.

Erwarte aber nicht, daß sich die Leute den Mund fusselig reden, um Dich 
zu bekehren.

Wenn es also nicht geht, weißt Du inzwischen ja, wo Du zu suchen hast.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S.:
Es hat sich landläufig als äußerst praktisch erwiesen, den Hausbau nicht 
mit dem Dach (Menüführung), sondern mit dem Fundament (Tasten einlesen) 
zu beginnen.

Eine schöne Übungsaufgabe dazu:
2 Taste + 2 LEDs, jede Taste muß ihre LED togglen, völlig unabhängig 
voneinander.


Peter

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mache erst tasten !! dann überlege dir ein menü

dein µC is im gegensaz zu DIR rasend schnell
tasten prellen nunmal

wenn du ohne entprellung drückst kanne s sein das der µC denkt du 
hättest 1000x gedrückt
deswegen erst entprellen !!!

dann weitermachen


und ich würde auch ein paar leute hier hören ... sonst bekommst du bald 
keine antworten mehr

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> P.S.:
> Es hat sich landläufig als äußerst praktisch erwiesen, den Hausbau nicht
> mit dem Dach (Menüführung), sondern mit dem Fundament (Tasten einlesen)
> zu beginnen.

Full ACK.

Und ehe man anfängt ein Menüsystem zu programmieren (wenn man dann 
soweit ist), setzt man sich hin und überlegt zuerst wie das Menü 
aussehen soll, welche Einträge es gibt, wie die zusammenhängen, wie die 
Tasten benutzt werden sollen, welche Angabe wo am LCD auftaucht, etc.
Bevor man dann den ersten Code schreibt, spielt man das dann am Papier 
durch. Dann sieht man zb. dass es höchst wahrscheinlich nicht sinnvoll 
sein wird, wenn auf dem LCD

 +------------------------------------+
 | > IC auswählen                     |
 |   IC simulieren                    |
 +------------------------------------+

steht und sonst nichts. Denn es erhebt sich die Frage: Wenn ich jetzt 
auf "IC simulieren" gehe, welches IC wird dann eigentlich simuliert? Wo 
sehe ich das?

Es lohnt sich daher (nachdem man seine Vorübungen mit Tasten und LCD 
abgeschlossen hat), sich die Menüstruktur auf dem Papier aufzumalen und 
im Geiste Bediener zu spielen und nach Schwachstellen, Inkonsistenzen 
und Unlogik in dieser aufgezeichneten Menüstruktur zu suchen.

ZB. Könnte man auf die Idee kommen, dass das Programm die ganze Zeit ein 
Gatter simuliert, im Hauptschirm auch angezeigt welches und durch Druck 
auf OK erscheint eine Liste von möglichen Gattern, aus denen eines 
ausgewählt wird (mittels der Taste "Weiter" kann man in einer Richtung 
durch diese Liste durchgehen und durch Druck auf OK wird es ausgewählt. 
Nach Auswahl geht es wieder zurück in den Hauptschirm, wo das momentan 
ausgewählte Gatter hingeschrieben wird und das Programm fängt sofort an, 
dieses Gatter zu simulieren.

Ooops. Jetzt braucht man gar keine Submenüs mehr :-) Der 'Menüpunkt' "IC 
simulieren" hat sich in Wohlgefallen aufgelöst.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Der 'Menüpunkt' "IC simulieren" hat sich in Wohlgefallen aufgelöst.

Die zweite Taste auch...

Im Auswahl-Menü:
Kurz drücken = Blättern
Lang drücken = Simulieren

In Simulation:
Kurz oder lang drücken: Zurück zum Auswahlmenü

;-)

...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes Lux schrieb:
>> Der 'Menüpunkt' "IC simulieren" hat sich in Wohlgefallen aufgelöst.
>
> Die zweite Taste auch...
>
> Im Auswahl-Menü:
> Kurz drücken = Blättern
> Lang drücken = Simulieren
>
> In Simulation:
> Kurz oder lang drücken: Zurück zum Auswahlmenü


Dazu muss man dann aber zwischen Kurz und Lang drücken unterscheiden 
können. Die PeDa Routinen können das aus dem Stand :-)

Wobei ich hier eher das Feature "Autorepeat" einsetzen würde, wenn die 
Liste der Auswahlmöglichkeiten lang wird und damit wohl oder übel wieder 
2 Tasten brauche.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die Liste der Auswahlmöglichkeiten lang wird...

Das wird wohl nicht der Fall sein. Denn es wird ja ein myAVR-Board mit 
Mega8 eingesetzt, da gibt es nur 6-Bit-Ports, von denen das LCD schon 
einen kompletten Port braucht. Tasten brauchen auch Pins, somit bleibt 
nicht mehr viel zum Simulieren (Eingänge für Schalter, Ausgänge für 
LEDs). Es wird wohl daher bei der einkanaligen Darstellung der Boolschen 
Grundfunktionen bleiben, wie sie Theo bereits weiter oben genannt hat:

And
Or
Not
Nand
Nor

Da käme dann vielleicht noch  EXOR und EXNOR dazu, aber dann hört es 
langsam auf (nagut, FFs und MUX gehen auch noch).

Na egal, ohne vernünftige Tastenentprellung geht da sowiso nichts. Ich 
habe es inzwischen aufgegeben, auf Peters Algorithmus zu verweisen, es 
sieht ja sonst so aus, als bekäme ich Prozente... ;-)

Ich benutze diesen Entprellalgorithmus sehr häufig (in ASM) und fahre 
ganz gut damit. Wer das nicht nutzen will, ist selbst schuld, wenn seine 
Programme spinnen...

;-)

...

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal vielen Dank für die vielen Antworten.

Ich habe nun die Tastenentprellung nach Peter Dannegger gemacht. Klappt 
ganz gut soweit.

Nun mach ich mich an die Sub-Menüs.


mfg Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich ein Sub-Menü erstelle, muss ich es ja nicht in einem neuen case 
machen sondern in dem case wo er in das Submenü springen soll.

Leider macht er es nicht. Wenn ich den neuen switch für das Sub-Menü in 
das case einbaue überspringt er das und geht da rein nachdem man mehrere 
male das Hauptmenü durchlaufen hat.

Weiß jmnd woran das liegt?
case 1:
   if(get_key_short( 1<<KEY0))
   {
      display (0);
      menue = 2;
      
      switch(sub)
      {
         case 0:
            if(get_key_long( 1<<KEY0))
            {
               display(1);
               sub = 1;
            }
            break;
 
         case 1:
            if(get_key_short( 1<<KEY0))
            {
               display(2);
               sub = 2;
            }
            break;
      }   
   }
   break;

case 2:
...
...
...


mfg Theo

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum UNTER menüs ?

läuft dein normales menü schon ?
oder warum fängst du alles von hinten an ?

Autor: Theo Rettisch (theo-rettisch)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Wie? Normales Menü?

Ich pack den Quellcode mal als Anhang...

Mein "normales" Menü läuft..ich drück einmal T1 dann erscheint "IC 
testen" ich drück nochmal T1 dann kommt "IC simulieren"...Wieder T1 
gedrückt erscheint wieder "IC testen".

Meinst du das?

Und wie soll ich deine Frage verstehen? Wie meinst du das mit "von 
hinten anfangen" ?

mfg Theo

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt verstehe ich deine Frage...(und die Beiträge vorher) Ich soll 
einfach nur die IC´s anzeigen lassen und bei einem kurzen Druck soll er 
z.b. testen und bei einem langen simulieren...oder?

mfg Theo

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde keine Submenus programmieren. Ich würde in diesem Fall alles 
in einer Menustruktur bearbeiten.

Je nach dem, wie groß die Variable ist, die den Menustatus kodiert, sind 
ausreichend viele Einträge in der Switch case Auswertung möglich.

Mal dir einfach mal ein Zustandsübergangsdiagramm auf, das alle 
Displayanzeigen (also Menupunkte) zeigt und wie man von einem in den 
nächsten kommt (z.B. durch Drücken von Tasten oder durch Timer oder 
durch Fertigstellung irgendwelcher Hintergrundprozesse).

Dann kannst du jedem Menupunkt eine Nummer geben.
Die Nummer sollte dem Zustand in der Statemachine entsprechen.

Und damit gibt es keine Submenus mehr, es ist alles in einer Case 
Anweisung untergebracht.

Peter

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst Dich erstmal entscheiden, was Pflicht_ und was _Kür ist. Geht 
es in der Aufgabestellung vorrangig um ein Menü mit Untermenüs, oder 
geht es um die Realisierung der Simulation der logischen Verknüpfungen. 
Danach entscheidet sich dann, wie umfangreich das Menü werden soll.

Es ist auch noch nicht bekannt (habe ich vielleicht übersehen), wie die 
Simulation aussehen soll. Sollen echte Pins als Ein/Ausgänge benutzt 
werden, an denen Schalter und LEDs angeschlossen werden? Oder soll die 
Simulation lediglich als Visualisierung auf dem LCD stattfinden? Es gibt 
da die verschiedensten Möglichkeiten.

...

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das nun so gemacht, dass man nur die einzelnen IC´s wählen kann 
und bei einem langen T1 druck soll getestet werden und bei einem langem 
T2 druck soll simuliert werden..

Simulation soll wie folgt laufen: Vom Lehrer bekomm ich n anderes Board 
mit mehr Ports. Somit kann ich mir einen "großen Sockel" bauen. Wenn 
dann ein "AND" IC gewählt wird soll an z.b. PC1 und PC2 drauf geachtet 
werden, dass wenn da eine -1- ist, dass dann an PC3 auch eine -1- 
ausgegeben wird.


mfg Theo

Autor: Theo Rettisch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nebenbei gefragt: Weiß jmnd woran das liegt, dass wenn ich mein 
USB-Kabel nicht am Board klemmen hab, dass dann die Taster nicht 
funktionieren?

mfg Theo

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie wird das teil mit strom versorgt ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes Lux schrieb:
> Du musst Dich erstmal entscheiden, was Pflicht_ und was _Kür ist.

Ein wahres Wort.

Neulinge tendieren gerne dazu, ihre Zeit mit Nebensächlichkeiten zu 
vertun (Sieht man oft):
Es ist ganz wichtig, dass ein Programm beim Hochfahren 5 verschiedene 
Startup Screens ausgibt, in denen in 7 verschiedenen Sprachen der Name 
des Programms und das Copyright ausgegeben wird. Um das zu 
implementieren brauchen sie 3 Wochen .... und dann wissen sie nicht mehr 
weiter und brauchen Hilfe weil der Abgabetermin schon morgen ist :-)

Neulinge tendieren auch gerne dazu, einen wunderschönen Programmheader 
zu malen. Da ist dann ihr halber Lebenslauf drinn und die komplette GPL, 
möglichst ansprechend formatiert und mit Rahmen aus * versehen. Dann 
schreiben sie noch  int main() {} und dann wissen sie nicht weiter.

Ich sag nicht, dass das alles nicht wichtig wäre. Das hat alles 
sicherlich seine Berechtigung. Aber wichtiger wäre zunächst, dass das 
Programm zumindest in Ansätzen seine Funktion erfüllt. Ein 
funktionierendes Programm ohne GUI ist zunächst erst mal ein Programm, 
dass eine Funktion erfüllt. Ein nicht funktionierendes Programm mit 
wunderschöner GUI hingegen ist zu nichts zu gebrauchen ausser als 
Anschauungsobjekt für einen Kunden um ihm zu zeigen was einmal werden 
wird. Und dann wird sowieso meistens alles ganz anders.

> Simulation soll wie folgt laufen: Vom Lehrer bekomm ich n anderes
> Board mit mehr Ports. Somit kann ich mir einen "großen Sockel"
> bauen. Wenn dann ein "AND" IC gewählt wird soll an z.b. PC1 und
> PC2 drauf geachtet werden, dass wenn da eine -1- ist, dass dann
> an PC3 auch eine -1- ausgegeben wird.

Bevor du deine Zeit jetzt mit großartigen Menüsteuerungen verbrauchst: 
Hast du den Teil schon versucht? Nimm einfach an, dein fiktiver Benutzer 
hätte AND ausgewählt. Kannst du ein Programm schreiben, welches genau 
dieses AND an den Pins PC1, PC2 und PC3 simuliert?

Was ist, wenn die Vorgabe ein OR Glied ist?

Was, wenn beide Gatter gleichzeitig im Programm sein sollen, und mit 
einer Taste soll umgeschaltet werden (Einen Tastendruck kannst du ja 
jetzt schon sauber auswerten). Wie kannst du programmintern 
unterscheiden, welche Einstellung jetzt gilt bzw. wie kannst du anhand 
dieser Einstellung die Gatterfunktion durchführen? Wie kannst du mehrer 
Gatterfunktionalitäten im Programm sinnvoll organisieren?

Und dann kannst du verallgemeinern auf mehrere verschiedene Gattertypen.
In deinem Fall (und das ist oft so) ist die einfachere Art der 
Entwicklung die, bei der Funktionalität anzufangen und sich von dort aus 
zum GUI vorzuarbeiten. Die Benutzerführung ergibt sich dann ganz von 
alleine und auch welche Benutzerführung sinnvoll und zweckmässig ist. 
Gerade unerfahrene Entwickler neigen oft dazu viel zu komplizierte 
Benutzerführungen mit 100-tausend Menüebenen zu entwerfen nur um dann 
festzustellen, dass das alles nicht praxistauglich ist, bzw das die 
Entwicklungszeit um ist und die eigentliche Funktionalität nicht richtig 
funktioniert.

Aber auch wenn du schon mit dem Menü anfängst, ist es sinnvoll eine Idee 
davon zu haben, wie das Programm in seiner eigentlichen Funktionalität 
intern funktionieren wird.

Zb. versteifst du dich im Moment darauf, dass es eine Unterscheidung 
zwischen "Auswahl" und "Simulation" geben muss. Aber wozu diese 
Unterscheidung? Warum kann das Programm nicht ständig irgendein Gatter 
simulieren und mit Tastendruck wird dieses 'irgendein' gegen ein anderes 
ausgetauscht.
void DisplayGatter( int was )
{
  lcd_clrscr();

  lcd_gotoxy( 0, 0 );

  if( was == 1 )
    lcd_puts( "AND / 1,2=I 3=O" );

  else if( was == 2 )
    lcd_puts( "OR  / 1,2=I 3=O" );

  else
    lcd_puts( "Fehler" );
}

int main()
{
   ...

  Gatter = 1;    // 1 ist UND, 2 ist ODER
  DisplayGatter( Gatter );

  while( 1 ) {

    if( Gatter == 1 )
      ... Funktionalität für UND

    else if( Gatter == 2 )
      ... Funktionalität für ODER


    if( get_key_short( 1<<KEY0) ) {   // Umschalttaste gedrückt worden?
      Gatter++;
      if( Gatter == 3 )
        Gatter = 1;

      DisplayGatter( Gatter );
    }

  }
}

Das implementiert zb. genau diese Funktionalität: Das Programm simuliert 
ein bestimmtes Gatter und mit Tastendruck wird auf ein anderes Gatter 
umgeschaltet. Und das alles in weniger Code als dein Menü mit Submenü 
verbraucht. Es ist einfacher zu implementieren, es ist einfacher und 
intuitiver zu benutzen. Ich will ein anderes Gatter, also drück ich auf 
den Knopf. Mehr braucht ein Benutzer nicht zu tun. Insbesondere muss er 
sich nicht merken, dass er mit einem langen Tastendruck zuerst die 
Simulation stoppen muss, dann mit einem anderen Tastendruck in die 
Auswahl gehen, dort das Gatter auswählen, dort wieder mit einem langen 
Tastendruck bestätigen, mit wieder einem anderen Tastendruck die 
Simulation wieder starten. Wenn das nicht kompliziert ist im Vergleich 
zu: Ich drück auf eine Taste und schalte damit auf das nächste Gatter 
um, dann weiß ich auch nicht.

Und wenn man will, könnte man da auch noch einen 2.ten Taster mit der 
Funktion "Simulation ein/ausschalten" einbauen. Wie der ins System 
eingreifen könnte sollte sich auch für Einsteiger völlig logisch 
ergeben.

Aber das fällt genau unter den Fall: zuerst machen wir mal die 
Funktionalität fertig und dann kommen die Komfortfunktionen dazu.

Aus Softwaresicht wäre es zunächst wichtiger die obige einfache Struktur 
so umzugestalten, dass sie gut auf 200 Gatter erweitert. D.h. zb das man 
sich darüber Gedanken macht, wie man die 200 if-else_if in 
Display_Gatter los werden kann. Das man sich Gedanken darüber macht, wie 
man zb die notwendige Umkonfigurierung der Ein/Ausgabepins beim 
Umschalten so gestaltet, dass das alles nicht in endlos lange 
switch-case Strukturen ausartet. Da warten noch viele Detailprobleme, 
die nichts mit Menüs oder langen und kurzen Tastendrücken zu tun haben 
oder damit, dass das Programm beim Hochfahren den zuletzt gewählten 
Gattertyp wieder automatisch selektiert (weil der im EEPROM steht).

Autor: Theo Rettisch (theo-rettisch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:
> wie wird das teil mit strom versorgt ?

Es wird über einen externen Gleichspannungsregler an´s Board 
geschlossen.

Desweiteren bekommt das Board über das mySmart USB einm wenig 
Stromzufuhr.

mfg Theo

Autor: Winfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein ähnliches Problem.
Bei mir sollen zwei Tasten gleichzeitig gegen GND gedrückt werden.
Es klappt aber nicht. Die einzelnen Tasten zeigen aber die gewünscht 
Funktion. Wo liegt mein Fehler?


if(!(DREH_TASTER_PIN & (1<<SONDER))&!(DREH_TASTER_PIN & 
(1<<FREQ_DEC)))//1.Taste+2.Taste
    {
   rit=1;freq++;;
   do{
    verzoegerung();
     }while (!(DREH_TASTER_PIN & (1<<FREQ_DEC))&!(DREH_TASTER_PIN & 
(1<<FREQ_DEC)));

vy73 de DL!YAR

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.