www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit loop_until_bit_is_clear


Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallöchen,

Ich habe hier 4 Taster die ich auswerten möchte,  um in einem Menü 
Rauf/Runter zu Scrollen.

Dazu hab ich folgende Funktion:
//-------------------------------------------------------
void BMZ_menue (void)
//-------------------------------------------------------
{

  TCCR0 = 1<<CS02^1<<CS00;      // divide by 1024
    TIMSK = 1<<TOIE0;        // enable timer interrupt
  sei();

  void(*menu_func)(int);
  LCD_clear();
  lcd_menu_aktiv = 0; // Menü wird angezeigt -> Hauptmenü
  lcd_page_aktiv = 1; // Hauptmenü aktiv!

  for(int i=0; i < 8; i++)
  {
    LCD_setCursorPos(i,2);

    if(lcd_menu_aktiv == i)
    {
      LCD_setCursorPos(i,0);
      LCD_write("* "),
      LCD_setCursorPos(i,2);
      LCD_write_P(menu_text[i]);
    }
    else
    LCD_write_P(menu_text[i]);
  }

  do
  {
    print_menu(lcd_menu_aktiv, lcd_page_aktiv); // Aktuells Menü ausgeben.
    
    loop_until_bit_is_clear(PINC, KEY_DOWN);
                // Hier warten bis die Taste Rauf oder Runter gedrückt wird und erst dann weiter machen...
    while( !(PINC & (1<< KEY_DOWN)) || !(PINC & (1<< KEY_UP)));

    if(get_key_short(1<<KEY_UP))
    {
      // Rauf Modus
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
    }
    if(get_key_short(1<<KEY_DOWN))
    {
      // Runter Modus
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_down);
    }
    if(get_key_long(1<<KEY_UP) && get_key_long(1<<KEY_DOWN))
    {
      if((pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_can_returned)) == 1)
      {
        lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
      }
    }

  }while(lcd_menu_aktiv >= 0);

  load_bmz_screen();
}

Die Funktion gibt mir im ersten Schritt das vollständige Menü aus, und 
soll dann erstmal "Warten" mittels dem loop_until_bit_is clear (Low 
Active Taster!) und erst dann weiter machen, wenn entweder Rauf/Runter 
Taste gedrückt wird.

Mit einer Taste klappt das soweit auch, nur wie schreibe ich meine While 
schleife so um, das sie auf beide Tasten reagiert also entweder Rauf 
oder Runter...?!

Habs bereits auch schon mit while((!get_key_short(1<<KEY_DOWN)) || 
(!get_key_short(1<<KEY_UP))); getestet, aber leider passiert dann 
nichts..

Ich nutze die Universelle Tasten Abfrage von peter.

Danke :)

Danke für eure hilfe.

Autor: David Madl (md2k7)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Wozu das Warten vor der Tastenabfrage überhaupt dienen soll, verstehe 
ich nicht... Wirf das Warten einfach raus, und rufe print_menu() dann 
auf, wenn eine Taste gedrückt wurde (also in den if(get_key_short(...)) 
drin).

Gruß
David

Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wozu das gut ist?

print_menu(lcd_menu_aktiv, lcd_page_aktiv); // Aktuells Menü ausgeben.

Gibt mir ein * vor jeweilig aktivem menüpunkt aus, d.H am Anfang der do 
wird's einmal ausgegeben da lcd_menu_aktiv = 0 hat (Hauptmenü) somit 
setzt er ein * vor's Hauptmenü.

Nun wartet er auf eine Eingabe, erfolgt diese, kommen wir zur auswertung 
der Tasten, somit wird eine neue ID in lcd_menu_aktiv geschrieben und 
dann sind wir oben an der do schleife wo eben genau die letzte funktion 
ausgegeben wird und gewartet wird.

somit kann ich das warten nicht entfernen, da er mir ständig das 
print_menu aufruft und unnötig befehle zum LCD schickt und da alles 
flackert..

Schade das hier keine weiteren leute geantwortet haben...

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

Bewertung
0 lesenswert
nicht lesenswert
Schmeiss das Warten trotzdem raus.
Du musst deine Denkweise umstellen.
Weg von:   Ich warte auf etwas
Hin zu:    Ich überprüfe ständig reihum ob irgendwelche Ereignisse
           eingetreten sind und führe die entsprechende Aktion
           dazu aus

Ein derartiges Ereignis könnte zb sein: Das Display ist 'dirty' und muss 
erneuert werden
  displayDirty = TRUE;   // erst malig wird auf jeden Fall hingemalt

  do
  {
    if( displayDirty )
    {
      print_menu(lcd_menu_aktiv, lcd_page_aktiv); // Aktuells Menü ausgeben.
      displayDirty = FALSE;    // jetzt ist das Display wieder up to date
    }
    
    if(get_key_short(1<<KEY_UP))
    {
      // Rauf Modus
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
      displayDirty = TRUE;
    }

    if(get_key_short(1<<KEY_DOWN))
    {
      // Runter Modus
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_down);
      displayDirty = TRUE;
    }

    if(get_key_long(1<<KEY_UP) && get_key_long(1<<KEY_DOWN))
    {
      if((pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_can_returned)) == 1)
      {
        lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
        displayDirty = TRUE;
      }
    }

  }while(lcd_menu_aktiv >= 0);

Jetzt wird das Display neu gezeichnet. Aber: nur dann wenn es 
tatsächlich notwendig ist.

Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,

Danke, das nenn ich wirklich mal eine positive Antwort mit der ich etwas 
anfangen kann.

Ich will auch eigentlich weg von den "Loops" und "Waits" weil's eben den 
gesamten Mikroprozessor ablauf aufhält, aber ich muss zu geben, ich 
hatte auch die gleiche Idee die du hattest, aber ich dachte mir das ist 
etwas umständlich. Aber wenn mir das nochmal jemand bestätigt bin ich zu 
frieden :)

Danke!

Autor: Daniel Steiner (sany)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Was mir gerade doch noch einfällt und zwar, ich hab die 4 Einzelnen 
Taster jeweils über einen eigenen 10K Widerstand an +5V gehängt( Active 
Low!) ist das wirklich richtig so?

Weil ich habe festgestellt wenn ich nur einen 10K an die +5V hänge und 
damit die anderen Taster zugleich "versorge" erkennt der Atmel das 
"Alle" gedrückt wurden, was ja so nicht stimmt, da vor dem 10K bei allen 
Tastern das Signal abfällt, was es eigtl. nicht sollte, vor dem 10K 
bleibts jedoch Konstant.

:-)

Gruß
Daniel

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber wenn mir das nochmal jemand bestätigt bin ich zu frieden :)

Ich bestätige das. Warteschleifen haben in Programmen nix zusuchen.


>ich hab die 4 Einzelnen Taster jeweils über einen eigenen 10K Widerstand an >+5V 
gehängt( Active Low!) ist das wirklich richtig so?

Es ist möglich, das so zu machen.


>ur einen ...damit ... zugleich ...

Was meinst du damit? Einen Widerstand für alle Taster? Das geht nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Daniel Steiner schrieb:
> Was mir gerade doch noch einfällt und zwar, ich hab die 4 Einzelnen
> Taster jeweils über einen eigenen 10K Widerstand an +5V gehängt( Active
> Low!) ist das wirklich richtig so?
Ja.

> Weil ich habe festgestellt wenn ich nur einen 10K an die +5V hänge und
> damit die anderen Taster zugleich "versorge"
Nach meinem Text2Schematics Interpreter wären die 4 Eingangspins dann 
alle miteinander verbunden.
> erkennt der Atmel das "Alle" gedrückt wurden, was ja so nicht stimmt,
> da vor dem 10K bei allen Tastern das Signal abfällt,
Doch, denn das ist ja das übliche Verhalten von verbundenen Pins.
> vor dem 10K bleibts jedoch Konstant.
Vor dem 10k Widerstand liegen dann ja auch die 5V Versorgung. Die 
sollten schon stabil sein.

Als Tipp:
Grundlagen der Reihen- und Parallelschaltung nochmal ansehen...  :-o


EDIT: du brauchst eigentlich gar keine externen Pullups, wenn du die 
internen Pullups der entsprechenden uC-Pins einschaltest...

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

Bewertung
0 lesenswert
nicht lesenswert
Daniel S. schrieb:
> Ich will auch eigentlich weg von den "Loops" und "Waits" weil's eben den
> gesamten Mikroprozessor ablauf aufhält, aber ich muss zu geben, ich
> hatte auch die gleiche Idee die du hattest, aber ich dachte mir das ist
> etwas umständlich.

Wenns mal etwas komplexer wird, wirst du feststellen dass diese Technik 
alles andere als umständlich ist :-) Dann stellt sich nämlich sehr 
schnell raus, dass alles andere zwar auf den ersten Blick einfach 
aussieht, dich aber ganz schnell in Schwierigkeiten bringt.

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.