Hallo mikrocontroller.net Gemeinde!
Da ich in Sachen yC-Programmierung noch ziemlich grün hinter den Ohren
bin und mich bestehende Forumeinträge nicht weitergebracht haben, hier
meine erste Frage:
Mit meinem Atmega8 will ich 3 LEDs mit einem Taster durchschalten
können. Sprich bei jedem Tastendruck in den nächsten Zustand schalten.
Das soll per Interrupt realisiert werden.
Was hab ich bei meinem Code vergessen? Die Ausgänge flackern wild hin
und her... :(
Vielen Dank für eure Mühe.
Gruß Michi
Hier mein Code:
Michi R. schrieb:> Mit meinem Atmega8 will ich 3 LEDs mit einem Taster durchschalten> können. Sprich bei jedem Tastendruck in den nächsten Zustand schalten.> Das soll per Interrupt realisiert werden.
Warum?
Taster und externer Interrupt sind eine blöde Idee, auch wenn das immer
wieder propagiert wird.
Entprellung
die Konmfortroutinen vom PeDa sind alles was man braucht um Tasten
zuverlässig auszuwerten.
so, so.
Und du denkst also, dass du innerhalb von 20 Millisekunden eine Taste
drücken und wieder loslassen kannst.
Der Interrupt kommt, solange der Pin auf Low-Pegel ist und auch auf
Low-Pegel bleibt! Bei dir: solange die Taste gedrückt ist, kommt ein
Interrupt nach dem anderen.
;) So ists besser:
MCUCR = ( 1<<ISC01 | 0<<ISC00 );
Macht aber noch immer nicht, was es soll...
Ich dachte, für diese einfache Anwendung tuts auch ein externer
Interrupt mit Taster! Bei der "Komfortroutine" blick ich ehrlich gesagt
nicht wirklich durch...
Michi R. schrieb:> ;) So ists besser:>> MCUCR = ( 1<<ISC01 | 0<<ISC00 );>> Macht aber noch immer nicht, was es soll...> Ich dachte, für diese einfache Anwendung tuts auch ein externer> Interrupt mit Taster!
Wie du siehst, ist das eben nicht einfach.
Einfach wäre ein Pollen in der Hauptschleife mit Vergleich ob sich der
zustand des Input-Pins verändert hat.
> Bei der "Komfortroutine" blick ich ehrlich gesagt> nicht wirklich durch...
Das macht nichts. Dazu funktionieren sie zu gut.
PS: Welchen Prozessor hast du wirklich? Ein Mega 8 hat kein Register
namens GIMSK
Gratuliere, du hast dir soeben den notwendigen Pullup Widerstand am Pin
2 abgeschaltet.
Jetzt weißt du auch, warum man derartige Rundum-Portzuweisungen nicht
macht.
Grrr. Bekomm ich doch gleich die volle Breitseite.
Karl Heinz Buchegger schrieb:> PS: Welchen Prozessor hast du wirklich? Ein Mega 8 hat kein Register> namens GIMSK
Ich hab nen Atmega8! Komisch, dass er da nicht rummeckert. ;)
Karl Heinz Buchegger schrieb:> Gratuliere, du hast dir soeben den notwendigen Pullup Widerstand am Pin> 2 abgeschaltet.
Wie gesagt, bin ziemlicher Anfänger! Umso dankbarer bin ich für deine
Korrektur.
Michi R. schrieb:> Grrr. Bekomm ich doch gleich die volle Breitseite.>> Karl Heinz Buchegger schrieb:>> PS: Welchen Prozessor hast du wirklich? Ein Mega 8 hat kein Register>> namens GIMSK>> Ich hab nen Atmega8! Komisch, dass er da nicht rummeckert. ;)
Ist in der Tat interessant.
Könnte ein Hinweis darauf sein, dass deine Projekteinstellungen nicht
korrekt sind.
Nichts desto trotz: ein Mega 8 hat laut Datenblatt kein GIMSK Register.
Atmel wird ja wohl wissen, wie die Dinger heißen
Michi R. schrieb:> Wenn auch sehr unprofessionell geschrieben
In der Tat
> ISR(INT0_vect)> {> _delay_ms(750);> i++;> }
sowas ist Murks.
Auf der einen Seite benutzt du einen Interrupt, damit nur ja alles
möglichst schnell reagiert (was eigentlich völlig sinnlos ist, denn für
deinen µC bewegst du dich sowieso in Zeitlupe), auf der anderen Seite
vertrödelst du dann genau hier die Zeit, damit dann ja alles, was der µC
nebenher zu machen hätte (in einem richtigen Programm) zum Stillstand
kommt.
So ist das Murks. Offen und ehrlich gesagt.
Einen durchgerosteten Kotflügel am Auto kann man auch mit Klebeband
reparieren. Hält sogar eine Zeit lang. Murks ist es trotzdem.
Den Link zum Artikel
Entprellung
hab ich dir schon gegeben.
Ich seh natürlich ein, dass die Komfortroutinen in ihrer vollen Pracht
nicht leicht zu durchschauen sind. Auf der anderen Seite hab ich dort
für 1 Taster das ganze aufgerollt und eine einfacher zu durchschauende
Version dafür geschrieben.
Es sei Dir gestattet, daß Du es nicht besser kannst (Deine Aussage), daß
Du aber lernen willst (auch Deine Aussgae) kann hier keiner erkennen. Du
willst nur die LED leuchten sehen, auch wenn Du den größtmöglichen Murks
ablieferst.
Lernen und Denken geht aber etwas anders.
Was ich dir allerdings zu gute halte ist, dass du den Interrupt brauchst
um den µC damit aus dem Sleep heraus zu holen. Was aber nichts daran
ändert, dass man Tastenabfragen wegen der Entprellung mittels Polling
macht.
> Du willst nur die LED leuchten sehen, auch wenn Du den größtmöglichen Murks> ablieferst.
Es tut mir wirklich leid, dass mir das Freude bereitet. Wo ist denn das
Problem, wenn ich mich langsam an die Sache rantasten möchte?
> Lernen und Denken geht aber etwas anders.
Gerne informiere ich dich über jeden einzelnen meiner Lernfortschritte.
kbuchegg, die Entprellung werde ich umgehend implementieren.
> Du aber lernen willst (auch Deine Aussgae) kann hier keiner erkennen.
---> jetzt aber! ;-)
Wobei. Das muss ich heute am Abend direkt mal ausprobieren.
Meiner Meinung nach und ohne das jetzt laufen gelassen zu haben, dürfte
diese Interrupt Lösung nicht funktionieren.
Das ist ein Level-Interrupt. Sobald die ISR betreten wird, wird das
zugehörige Interrupt Flag erneut gesetzt, weil ja die Taste noch immer
gedrückt ist, der Level also immer noch anliegt. Der delay_ms ändert
daran nichts. Er sorgt mit seinen 750ms lediglich dafür, dass ich als
Benutzer eine Chance habe, die Taste wieder loszulassen, ohne dass
gleich alles Amok läuft. Aber die Schaltstufe um lediglich 1 zu erhöhen
dürfte mir damit nicht gelingen. Mit einmal kurz drauf drücken erhöht
sich die Stufe um mindestens 2. Das kann ich als Benutzer gar nicht
verhindern.
Denke ich jetzt mal. Aber wie gesagt: das will ich tatsächlich mal
ausprobieren, wie das jetzt wirklich ist. Denn da bin ich mir jetzt auch
unsicher. Ich hab da noch im Hinterkopf, dass die Level Interrupts ein
bisschen anders funktionieren als die anderen.
Michi R. schrieb:> Wie gesagt, bei mir läufts.>> Ich dachte, das Flag ist "geschützt", solange die ISR läuft?
Nö.
Keines der Interrupt Request Flags ist in irgendeiner Art und Weise
geschützt. Sobald die ISR ausgelöst wird, werden sie wieder gelöscht.
Wobei beim INTF0 Flag in der Doku steht
1
This flag is always cleared when INT0 is configured
2
as a level interrupt.
Von daher verhält sich das in dem Fall ein wenig anders.
Edit: Du redest vom globalen Interrupt Flag.
Aber der komplette Interrupt Mechanismus ist ein wenig komplexer als nur
dieses 1 Flag. Es muss ja auch einen Mechanismus geben, der das
Auftreten eines Ereignisses registriert und festhält, während die CPU
gerade in einer ISR einen ganz anderen Interrupt bearbeitet. Das
Auftreten dieses 2-ten Interrupt Ereignisses soll ja deswegen nicht
verloren gehen.