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); }
Markus S. schrieb: > while (i==2) > { > PORTC &=~(1<<PC0); > _delay_ms(500); > PORTC |=(1<<PC0); > _delay_ms(500); > } wie soll i in dieser Schleife jemals seinen Wert ändern? -> du hast eine logische Endlosschleife gebaut, die wenn sie einmal betreten wurde, nie wieder verlassen werden kann.
Du gehst in die While-Schleife wenn i = 2 ist. In der Schleife änderst du aber i nie mehr => Endlosschleife! :) lg
Im übrigen: so wie du dir das vorstellst, so wird das nichts mit der Taste. Um Tastendrücke auszuwerten siehe zb den Link Entprellung
Markus S. schrieb: > 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. Das hast du ja auch so programmiert: Markus S. schrieb: > while (i==2) > {
Hallo, vielen Dank für die Antworten. Aber, wie muß ich es denn machen? Grüße Markus
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.
Hallo, und wie kann ich eine weitere Tastenabfrage einbauen? Ich bin leider Anfänger und kenn mich noch nicht so gut aus. Grüße Markus
Karl Heinz Buchegger schrieb: > -> du hast eine logische Endlosschleife gebaut, die wenn sie einmal > betreten wurde, nie wieder verlassen werden kann. Das ist eine Hammerschleife. Um sie zu verlassen, muss man einmal kräftig mit dem Hammer auf den µC hauen. :-) Gruss Harald
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.
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. Gruss Harald
Hallo Harald, die Taste ist hardwaremäßig entprellt. Wie muß ich diese Portabfrage denn in den Code einbauen? Grüße Markus
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.
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.
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.
Karl Heinz Buchegger schrieb: > da müsste man noch was machen. Ja. Kommt nicht so deutlich rüber. Ich meinte mit '// Taste abfragen' eine komplette Funktion, welche diesen Status zurückgibt. (Ich würde erstmal auf loslassen testen: also 'gedrückt' merken, dann bei loslassen in einen 'Wartezustand' gehen und 'gedrückt' zurückgeben.)
Ralf G. schrieb: > Karl Heinz Buchegger schrieb: >> da müsste man noch was machen. > > Ja. Kommt nicht so deutlich rüber. Ich meinte mit '// Taste abfragen' > eine komplette Funktion, Ah, ok. So macht das natürlich Sinn.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.