Taster mit LED Dauer, Blinken

OP #3150061
Lesenswert?

Hallo,

ich versuche folgendes mit einem Atmega8:

Taster 1 mal drücken - LED dauernd an-
Taster 2 mal drücken - LED blinken.
Taster 3 mal drücken - LED aus.

Mein Problem ist folgendes:

wenn ich den Taster 1 mal drücke geht die LED an.
Beim 2. drücken blinkt die LED, geht aber nie mehr aus der Schleife 
raus, ich kann also so oft drücken wie ich will, es ändert sich nix 
mehr.
Wo liegt der Fehler?

Vielen Dank für Eure Hilfe.

#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
DDRC = 0x01;
PORTC = 0x00;
DDRB = 0x00;
PORTB = 0xFF;

int i=0;

while (1)
{
  if (!(PINB & (1<<PB1)))
  {
    i++;
  _delay_ms(200);
  }
  if (i==1)
  {
    PORTC |=(1<<PC0);
  }
  while (i==2)
  {
  PORTC &=~(1<<PC0);
  _delay_ms(500);
  PORTC |=(1<<PC0);
  _delay_ms(500);
  }
  if (i==3)
  {
  PORTC &=~(1<<PC0);
  }
}
return(0);
}
#3150102
Lesenswert?

Markus S. schrieb:
> Hallo,
>
> vielen Dank für die Antworten.
> Aber, wie muß ich es denn machen?

Das ist jetzt nicht leicht zu beantworten.
Denn die eigentlich richtige Antwort lautet: Die Tastenabfrage muss 
komplett anders gemacht werden. Im Grunde müsste man das Komplettsystem 
anders machen, wenn man es vernünftig macht.

Als momentaner Ausweg:
 entweder keine Schleife machen, sondern nur ein if, in dem genau 1 
einziger Blinker stattfindet. Danach gehts wieder weiter und dein 
Programm hat wieder die Chance den Taster abzufragen (wenn dein Benutzer 
dann auch zum richtigen Zeitpunkt die Taste drückt)
Oder du baust in die Schleife eine weitere Tastenabfrage rein. Denn 
irgendwie muss i ja auch eine Chance bekommen, seinen Wert zu ändern.

Aber eigentlich ist der ganze Ansatz untauglich. Und das beginnt schon 
mit dem Blinken, welches durch Warteschleifen realisiert wird. _delay_ms 
ist selten die Lösung für irgendwas, sehr oft aber das Problem.



Einzelne Tastendrücke zuverlässig abzufragen, ist erstaunlicherweise gar 
nicht so einfach, wie man meinen sollte.
#3150117
Lesenswert?

M. S. schrieb:
> Hallo,
>
> und wie kann ich eine weitere Tastenabfrage einbauen?
> Ich bin leider Anfänger und kenn mich noch nicht so gut aus.

Dann bist du momentan in der Situation, dass du versuchst vorzugreifen 
und Dinge zu tun, die du noch nicht kannst.
Und ich sag das nicht, weil ich dich ärgern will. Aber das Thema 
'einzelne Tastendrücke sauber auszuwerten' ist tatsächlich etwas, was 
schon etwas fortgeschrittenere Programmierer erfordert. Nicht umsonst 
wird dieses Thema im AVR-Tutorial erst in einem späteren Kapitel 
angesprochen.
#3150127
Lesenswert?

Harald Wilhelms schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Aber das Thema
>> 'einzelne Tastendrücke sauber auszuwerten' ist tatsächlich etwas, was
>> schon etwas fortgeschrittenere Programmierer erfordert.
>
> Vielleicht wäre es für den Anfang leichter, die Entprellung hardware-
> mäßig zu machen. Dann würde sich das Problem auf eine einfache Port-
> abfrage reduzieren.

Noch nicht ganz. Es geht auch darum, dass ein einzelner Tastendruck nur 
einmalig zu einer Erhöhung von i führt. Dazu kommt noch das Problem, 
dass der Tastendruck auch dann registriert werden muss, wenn der µC 
gerade in den _delay_ms vom Blinken feststeckt.

Alles in allem nicht so einfach zu machen. Für eine ordentliche 
Tastenauswertung (und Entprellung) sind nun mal Timer samt Polling in 
der ISR voraussetzung. Nur dann wirds wirklich ordentlich.
#3150136
Lesenswert?

M. S. schrieb:
> Aber, wie muß ich es denn machen?

'Billigvariante:'
1
...
2
uint8_t pos = 0;
3
while (1)
4
{
5
  _delay_ms(10);   // du brauchst eine Zeitbasis
6
// Taste abfragen
7
  if (gedrueckt)
8
  {
9
    pos++;
10
    if (pos == 3) pos = 0;
11
  }
12
  switch (pos)
13
  {
14
    case 0: // Funktion für LED an
15
      ...
16
      break;
17
    case 1: // Funktion für LED blinken (Zähler verwenden, kein delay!)
18
      ...
19
      break;
20
    case 2: // Funktion für LED aus
21
      ...
22
      break;
23
  }
24
}

Edit:
Wollte ich nur noch mal hervorheben:
Karl Heinz Buchegger schrieb:
> Es geht auch darum, dass ein einzelner Tastendruck nur
> einmalig zu einer Erhöhung von i führt. Dazu kommt noch das Problem,
> dass der Tastendruck auch dann registriert werden muss, wenn der µC
> gerade in den _delay_ms vom Blinken feststeckt.
#3150145
Lesenswert?

1
// Taste abfragen
2
  if (gedrueckt)
3
  {
4
    pos++;
5
    if (pos == 3) pos = 0;
6
  }

da müsste man noch was machen. Sonst wechselt der 'Zustand' der LED alle 
10ms bei gedrückter Taste.

Neuer Ansatz
1
  Tastenzustand_jetzt = Taste abfragen
2

3
  if (Tastenzustand_jetzt == gedrueckt &&
4
      Tastenzustand_vorher == nicht gedrückt )
5
  {
6
    pos++;
7
    if (pos == 3)
8
      pos = 0;
9
  }
10
  Tastenzustand_vorher = Tastenzustand_jetzt;

mit den 10ms delay kommt das noch so einigermassen hin.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren