mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Simpeles Menü - Denkfehler


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Mikrocontroller Freunde,

ich weiss, dass es schon hunderte von Threads zu Menüs usw. gibt, aber 
anscheinend bin ich zu doof dafür und darum, hab ich mehr selbst was 
mehr oder weniger schlaues überlegt oder zumindest versucht, weil ich 
mit den Funktionspointern (noch) nicht klarkomme.

Jedoch hab ich immer das Problem, dass ich aus dem Menü rauslaufe und 
demnach Unerwünschte Dinge auftreten.

Es wird ein 2x16 Display verwendet, mit einem ATMega32.

Hier die relevanten Code-Stellen :

...

unsigned int menu_size=5;

...
  while(1)
  {
    // Entertaste zur Menüaktivierung bzw. bzw Ausfürung der  Funktion
    if(debounce(&IO_PIN, IO_B_ENTER))
    {
      if(!menuOnScreen)
      {
        menuOnScreen=1;
        show_menu(menu_index);
      }
      else
      {
        exec_function(menu_index);
        menuOnScreen=0;
        menu_index=0;
      }
    }
    if(debounce(&IO_PIN, IO_B_DOWN) && menuOnScreen)
    {
      if(menu_index<menu_size)
      menu_index++;
    }
    if(debounce(&IO_PIN, IO_B_UP) && menuOnScreen)
    {
      if(menu_index>0)
      menu_index--;
    }
    if(menuOnScreen && !(menu_tmp==menu_index))
    {
      show_menu(menu_index);
    }
  }


----------------------

volatile char menu_text[6][16] = {"Spuelen", "Spueldauer", "Test2", "Test3", "Exit", " "};



void show_menu(uint8_t menu_index)
{
  lcd_write((char*)menu_text[menu_index],0,1);
  lcd_write((char*)menu_text[menu_index+1],0,2);
}

Ich hoffe jemand kann mir weiterhelfen.
Vielen Dank schomal im Voraus, für alle die sich Mühe geben werden mir 
zu helfen :-)

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

Bewertung
0 lesenswert
nicht lesenswert
Stefan schrieb:

> Hier die relevanten Code-Stellen :

Ohne den Code grossartig analysiert zu haben


>     if(debounce(&IO_PIN, IO_B_DOWN) && menuOnScreen)
>     {
>       if(menu_index<menu_size)
>       menu_index++;
>     }

Hier muss es
       if(menu_index<menu_size-1)
       menu_index++;

heissen.
Du darfst nur dann zum nächsten INdex gehen, wenn auch noch einer 
existiert.

Probiers mit Zahlen aus
Dein Menü besteht aus 5 Einträgen
D.h. der letzte gültige hat die Nummer 4.
Daraus folgt, dass du den Index noch erhöhen darfst, wenn der Index 3 
ist. Ist er bereits 4, darf nicht mehr erhöht werden.

menu_size ist also 5
menu_index sei bereits 4    -> darf nicht mehr erhöht werden
                               menu_index < menu_size würde das aber
                               erlauben

>     if(debounce(&IO_PIN, IO_B_UP) && menuOnScreen)
>     {
>       if(menu_index>0)
>       menu_index--;
>     }

... aus dem gleichen Grund hast du ja hier auch > 0 benutzt und nicht == 
0


PS: überleg dir mal, ob
       if( menu_index < menu_size-1 )
         menu_index++;

nicht einfacher zu lesen ist, als
       if(menu_index<menu_size-1)
       menu_index++;

Du hast seit Kindesbeinen gelernt, dass zwischen den Wörtern mindestens 
ein Leerzeichen kommt. Das ist auch 
gutso,dennansonstenistdieserSatznämlichziemlichschwerzulesen.

Dein Gehirn ist darauf trainiert, einzelne Wörter anhand dieser 
Leerzeichen zu erkennen. Nutze das, und schreib nicht alles in einer 
Wurscht dahin, so dass du 20 Sekunden brauchst um in
       if(menu_index<menu_size-1)
erst mal die einzelnen Wörter und wie sie zusammenhängen erkennen zu 
können. Einige strategisch platzierte Leerezeichen können eine Menge 
ausmachen. Unter anderem den Unterschied zwischen nicht wartbarem Code 
und Code der eine Freude zu lesen ist.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

Danke erstmal für die Anregungen mit dem Leerzeichen, du hast natürlich 
recht, was die Lesbarkeit angeht und ich gelobe Besserung :-)

Mit dem "menu_size - 1", hast du glaube ich aber nicht recht, da ich 6 
Felder habe ( das letzte ist leer ):
volatile char menu_text[6][16] = {"Spuelen", "Spueldauer", "Test2", "Test3", "Exit", " "};

Aus diesem Grund verstehe ich ja auch nicht, warum er aus dort 
rauslaufen kann. Bei den Tests gestern konnte ich auch nicht auf den 1. 
Eintrag zurückgehen, wenn ich mal von diesem weg war.

Danke

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> a ich 6 Felder habe ( das letzte ist leer ):
Ja, von 0 bis 5   ;-)
Also kann dein Menüpointer menu_index die Werte 0-5 annehmen.
Und dann das:
lcd_write((char*)menu_text[menu_index+1],0,2);
Yeah, hinter das Array gegriffen...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,

Danke, jetz hab sogar ich das verstanden :D

Ich war irgendwie der festen Überzeugung, dass menu_index nicht 5 werden 
kann ... nach genauerer Überlegung geht es aber doch :)

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

Bewertung
0 lesenswert
nicht lesenswert
PS

Wenn du das so formulierst
const char * menu_text[]=
     { "Spuelen", "Spueldauer", "Test2", "Test3", "Exit", " "};

#defien MENU_SIZE  ( sizeof(menu_text) / sizeof(*menu_text) )

Dann brauchst du dir auch nicht den Wolf zählen, wieviele Einträge du 
wirklich hast. Das erledigt dann der Compiler für dich.

Versuch immer, Wissen aus deinem Kopf in das Programm einzubauen.
Im Moment musstest du wissen, dass menu_size immer um 1 weniger ist, als 
du Einträge im Menü hast. Das ist nicht gut, denn in 3 Wochen weißt du 
das nicht mehr. Diese Information ist aber wichtig, wenn du weitere 
Menüpunkte einbaust.

-> Lass den Compiler abzählen, wieviele Menüpunkte du hast und schreib 
dein Programm so, dass sich ausgehend von dieser Anzahl alles weitere 
von selbst im Programm regelt.

Auch die Sache mit dem letzten, leeren, Einträg fällt in diese 
Kategorie. Wenn der letzte Eintrag sowieso immer leer ist, dann kann ihn 
sich das Programm auch bei Bedarf selber generieren.

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

Bewertung
0 lesenswert
nicht lesenswert
Wenn du zb das ganze so formulierst ...

(Warnung: ungetesteter Code)
const char * menu_text[]=
     { "Spuelen", "Spueldauer", "Test2", "Test3", "Exit" };

#define MENU_SIZE  ( sizeof(menu_text) / sizeof(*menu_text) )


#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

....

  menu_index   = 0;
  menu_tmp     = 100;
  menuOnScreen = TRUE;

  while(1)
  {
    // Entertaste zur Menüaktivierung bzw. bzw Ausfürung der  Funktion
    if(debounce(&IO_PIN, IO_B_ENTER))
    {
      if( !menuOnScreen )
      {
        menuOnScreen = TRUE;
        show_menu( menu_index );
      }
      else
      {
        exec_function( menu_index );
        menuOnScreen = FALSE;
        menu_index = 0;
      }
    }

    if( debounce(&IO_PIN, IO_B_DOWN) && menuOnScreen )
    {
      if( menu_index < MENU_SIZE - 2 )
        menu_index++;
    }
    if( debounce(&IO_PIN, IO_B_UP) && menuOnScreen )
    {
      if( menu_index > 0 )
        menu_index--;
    }

    if( menuOnScreen && ( menu_tmp != menu_index ) )
    {
      show_menu( menu_index );
      menu_tmp = menu_index;
    }
  }

 ...

void show_menu( uint8_t menu_index )
{
  lcd_write( menu_text[ menu_index++ ], 0, 1 );

  if( menu_index < MENU_SIZE )
    lcd_write( menu_text[menu_index], 0, 2 );
  else
    lcd_write( "               ", 0, 2 );
}

dann kümmert sich der Code ganz von alleine um etwaige Änderungen im 
Menü. Willst du einen Menüpunkt mehr im Programm. zb "Setup"
const char * menu_text[]=
     { "Spuelen", "Spueldauer", "Test2", "Test3", "Setup", "Exit" };

dann fügst du einfach nur diesen neuen Punkt ein, und alles weitere 
regelt sich von selbst.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm ohne jetz weiter auf dein menü einzugehen
aber ich würde vlt versuchen  dein menü anders aufzubauen

wenn du nun ein paar texte mehr machst ist dein RAM voll und derµC 
stürzt ständig weg  weil der stack überläuft

sinnvoller ist es texte in den flash zu legen

ebenso ist ein 2dim. array für texte auch nicht schön
da du dort speicher verbrennst ohne das du ihn nutzt
dein 6tes " "  verbraucht trotzdem 17 byte

vlt sowas :

// hier texte definieren
const char text_1[] ROGMEM = " blih";
const char text_2[] ROGMEM = " blah";
const char text_3[] ROGMEM = " blubb";
const char text_4[] ROGMEM = " blubberdiblub";

// array von zeigern auf die texte erstellen
const char *message[] PROGMEM =
{
text_1,
text_2,
text_3,
text_4
};


deine lcd_write kopierst du und nennst sie zb  lcd_write_P
in dieser funktion holst du das byte vorher aus dem flash
pgm_read_byte( ...)
und schreibst das dann zum LCD


wenn du nun einen text schreiben willst

lcd_write_P ( (const char*) pgm_read_word( &message[i]) );

i ist hierbei eine variable wie man mit dem menüindex koppeln kann


man kann auch ohne dem zeigerarray arbeiten und einfach

lcd_write_P(text_1); schreiben

oder

lcd_write_P( PSTR(" blubbblubb") );


typisch für lcd_write ist ja :

lcd_write( char *string)
{
  while(*string)
    lcd_data( *string++);
}

die P ist etwas anders
lcd_write_P(const char *string)
{
  char data;
  while( (data = pgm_read_byte(string++)) != '\0')
    lcd_data( data);
}


so ganz grob ...

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.