Forum: Mikrocontroller und Digitale Elektronik Problem mit loop_until_bit_is_clear


von Daniel S. (Gast)


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:
1
//-------------------------------------------------------
2
void BMZ_menue (void)
3
//-------------------------------------------------------
4
{
5
6
  TCCR0 = 1<<CS02^1<<CS00;      // divide by 1024
7
    TIMSK = 1<<TOIE0;        // enable timer interrupt
8
  sei();
9
10
  void(*menu_func)(int);
11
  LCD_clear();
12
  lcd_menu_aktiv = 0; // Menü wird angezeigt -> Hauptmenü
13
  lcd_page_aktiv = 1; // Hauptmenü aktiv!
14
15
  for(int i=0; i < 8; i++)
16
  {
17
    LCD_setCursorPos(i,2);
18
19
    if(lcd_menu_aktiv == i)
20
    {
21
      LCD_setCursorPos(i,0);
22
      LCD_write("* "),
23
      LCD_setCursorPos(i,2);
24
      LCD_write_P(menu_text[i]);
25
    }
26
    else
27
    LCD_write_P(menu_text[i]);
28
  }
29
30
  do
31
  {
32
    print_menu(lcd_menu_aktiv, lcd_page_aktiv); // Aktuells Menü ausgeben.
33
    
34
    loop_until_bit_is_clear(PINC, KEY_DOWN);
35
                // Hier warten bis die Taste Rauf oder Runter gedrückt wird und erst dann weiter machen...
36
    while( !(PINC & (1<< KEY_DOWN)) || !(PINC & (1<< KEY_UP)));
37
38
    if(get_key_short(1<<KEY_UP))
39
    {
40
      // Rauf Modus
41
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
42
    }
43
    if(get_key_short(1<<KEY_DOWN))
44
    {
45
      // Runter Modus
46
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_down);
47
    }
48
    if(get_key_long(1<<KEY_UP) && get_key_long(1<<KEY_DOWN))
49
    {
50
      if((pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_can_returned)) == 1)
51
      {
52
        lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
53
      }
54
    }
55
56
  }while(lcd_menu_aktiv >= 0);
57
58
  load_bmz_screen();
59
}

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.

von David M. (md2k7)


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

von Daniel S. (Gast)


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...

von Karl H. (kbuchegg)


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
1
  displayDirty = TRUE;   // erst malig wird auf jeden Fall hingemalt
2
3
  do
4
  {
5
    if( displayDirty )
6
    {
7
      print_menu(lcd_menu_aktiv, lcd_page_aktiv); // Aktuells Menü ausgeben.
8
      displayDirty = FALSE;    // jetzt ist das Display wieder up to date
9
    }
10
    
11
    if(get_key_short(1<<KEY_UP))
12
    {
13
      // Rauf Modus
14
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
15
      displayDirty = TRUE;
16
    }
17
18
    if(get_key_short(1<<KEY_DOWN))
19
    {
20
      // Runter Modus
21
      lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_down);
22
      displayDirty = TRUE;
23
    }
24
25
    if(get_key_long(1<<KEY_UP) && get_key_long(1<<KEY_DOWN))
26
    {
27
      if((pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_can_returned)) == 1)
28
      {
29
        lcd_menu_aktiv = pgm_read_byte(&menu_rom_data[lcd_menu_aktiv].menu_up);
30
        displayDirty = TRUE;
31
      }
32
    }
33
34
  }while(lcd_menu_aktiv >= 0);

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

von Daniel S. (Gast)


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!

von Daniel S. (sany)


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

von Matthias L. (Gast)


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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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...

von Karl H. (kbuchegg)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.