Hi, ich hab ein glaub ich relativ einfaches Problem, welches ich aber irgendwie nicht gelöst bekomme. Also ich löse mit einem Taster (an PD2 angeschlossen) die ISR aus. Nun möchte ich das ich bei jedem durchlauf dieser Routine um 1 hochgezählt wird. Also auf Deutsch ich möchte die Tastenanschläge von PD2 zählen und diese in einer Variable an die main übergeben? Entprellt hab ich den Taster und in die ISR komm ich auch(klappt mit einem anderen Programm super)! Kann irgendwer helfen?? MfG
Ohne deinen Code zu kennen, gibt es leider zu viel unbekanntes, als das man deine Frage wirklich beantworten könnte. Wo liegt denn dein konkretes Problem? Kannst du die Tastenanschläge nicht zählen? Weil eventuell zu viele gezählt werden, Dann funktioniert dein entprellen nicht richtig! Oder Zählst du zu wenige Tastenanschläge? Auch dann würde ich auf deine Entprellung tippen. Oder schaffst du es nicht, die richtig gezählte Anzahl aus der ISR an das Hauptprogramm zu übermitteln? Für letzteres würde man eine globale Variable verwenden, die allerdings volatile deklariert werden muss, damit es vernünftig klappt. Außerdem musst du, wenn die Variable größer als 1 Byte ist, dafür sorgen, das der Zugriff auf die Variable im Hauptprogramm nicht durch die ISR unterbrochen werden kann. Also am besten kurz vorher die Interrupts sperren und danach freigeben: http://www.mikrocontroller.net/articles/Interrupt#Interruptfeste_Programmierung
Hey Danke für die schnelle Antwort! Hier ist mein Code: #include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> volatile int32_t a = 0; ISR(INT0_vect) { a=a+1; } int main(void) { DDRB |= (1<<PB4); DDRD &= ~(1<<PD2); PORTD |= (1<<PD2); MCUCR |= (1<<ISC01) | (1<<ISC00); GICR |= (1<< INT0); sei(); if(a==1) { PORTB |= (1<<PB4); } while(1); }
Das erste, was mir aufgefallen ist, ist, das a als int32_t deklariert ist. Muss das sein? Der Atmel ist ein 8-Bit Prozessor. 32Bit Additionen/Vergleiche sind für einen 8-Bitter recht aufwendig. Erwartest du wirklich 2.14 Billionen Tastendrücke? Ich würde a auch nicht als int sondern als unsigned int deklarieren. Dann fiel mir auf, das du im Code überhaupt keine Entprellung hast! Ein real existierender Taster prellt aber immer! Ein Tastendruck prellt etliche male nach, so das du diesen einen Tastendruck 10, 20mal zählst. Ist ist deshalb nicht besonders klug den Taster direkt einen Interrupt auslösen zu lassen. Besser ist es den Taster innerhalb eines periodischen Timerinterrupts abzufragen, oder falls du keine zeitkritische Anwendung im Sinn hast, diesen mit der Warteschleifen Methode abzufragen. Entprellung: http://www.mikrocontroller.net/articles/Entprellung Dann ist natürlich auch sofort klar weshalb dein Code nicht funktioniert:
1 | if(a==1) |
2 | { |
3 | PORTB |= (1<<PB4); |
4 | } |
Aufgrund des Prellen ist es sehr unwahrscheinlich das a genau zu dem einen und einzigen Zeitpunkt, wo du a abfragst den Wert 1 hat. Der Vergleich wird also niemals true! Außerdem ist die Position des Vergleichs schlecht gewählt. Er müsste in der while schleife sein und ist leider auch nicht mit cli()/sei() interruptfest gestaltet.
Also entprellt ist die Taste mit mit na schönen 100nF Kapazität! Ist der Zähler sonst in Ordnung so? also müsste a um 1 erhöht werden wenn ich die Taste drücke?
1 | int main(void){ |
2 | DDRB |= (1<<PB4); |
3 | |
4 | DDRD &= ~(1<<PD2); |
5 | PORTD |= (1<<PD2); |
6 | |
7 | MCUCR |= (1<<ISC01) | (1<<ISC00); |
8 | GICR |= (1<< INT0); |
9 | sei(); |
10 | |
11 | if(a==1) |
12 | {
|
13 | PORTB |= (1<<PB4); |
14 | }
|
15 | |
16 | while(1) { |
17 | //hier sollte der "a"-Vergleich stehen!
|
18 | } //ENDLOSSCHLEIFE |
19 | }
|
Deine Code ist falsch. Du prüfst am Anfang genau einmal, ob die Anzahl der Tastendrücke stimmt, danach gehst Du in eine Endlosschleife und dein Hauprprogramm steht still. Prüfe die Anzahl der Tastendrücke am Besten innerhalb der Endlosschleife!
Aber wenn ich in die ISR springe, was er durch Tastendruck ja macht, läuft er die main doch von vorne durch oder nicht? das heißt er müsste den wert von a doch wieder neu vergleichen!?! oder versgteh ich das falsch??
MicroDave schrieb: > Aber wenn ich in die ISR springe, was er durch Tastendruck ja macht, > läuft er die main doch von vorne durch oder nicht? Das wäre aber fatal. Nein. Ein Interrupt unterbricht die momentane Programmausführung, bei dir die while-Schleife. Nach Beendigung der ISR geht es genau dort weiter, wo der Interrupt unterbrochen hat. Genau das ist ja der Sinn eines Interrupts: Das normale Hauptprogramm arbeitet vor sich hin. Plötzlich tritt ein Ereignis auf, welches von der ISR kurzfristig behandelt wird und danach macht das Hauptptogramm weiter als ob nichts passiert wäre. Du bastelst an deinen Projekten ja auch dort weiter wo du aufgehört hast wenn die Unterbrechung "Mittagessen" vorbei ist und fängst nicht jedesmal wieder von vorne an.
Oh man stimmt! Sorry das wär ja sonst sowas wie ein Reset. Also ich habe jetzt mal meine Code etwas verändert! Ich will ja die Variable a wieder zurückgeben, aber irgendwie geht das nicht so wie ich mir das vorstelle. Er soll bei Tastendruck die Variable a toggeln und diesen neuen Wert an die do-while Schleife übergeben. Steh voll aufm Schlauch! #include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> volatile int8_t a; ISR(INT0_vect) { a ^= 1; } int main(void) { DDRB |= (1<<PB4); DDRD &= ~(1<<PD2); PORTD |= (1<<PD2); MCUCR |= (1<<ISC01) | (1<<ISC00); GICR |= (1<< INT0); sei(); do { PORTB |= (1<<PB4); } while(a==1); while(1) { return a; } }
MicroDave schrieb: > Oh man stimmt! Sorry das wär ja sonst sowas wie ein Reset. Also ich habe > jetzt mal meine Code etwas verändert! Ich will ja die Variable a wieder > zurückgeben, zurückgeben an wen? Dein Programm ist schon im Hauptprogramm, da ist nichgts mehr, an das du einen Wert zurückgeben könntest!
1 | int main(void) |
2 | {
|
3 | DDRB |= (1<<PB4); |
4 | |
5 | DDRD &= ~(1<<PD2); |
6 | PORTD |= (1<<PD2); |
7 | MCUCR |= (1<<ISC01) | (1<<ISC00); |
8 | GICR |= (1<< INT0); |
9 | sei(); |
10 | |
11 | while( 1 ) { |
12 | if( a > 1 ) |
13 | PORTB |= (1<<PB4); |
14 | }
|
15 | }
|
Du solltest wirklich mit einfacheren Dingen als mit Interrupts anfangen, wenn dir das Verständnis dessen was hier passiert Schwierigkeiten macht.
Karl heinz Buchegger schrieb: > Du solltest wirklich mit einfacheren Dingen als mit Interrupts anfangen, > wenn dir das Verständnis dessen was hier passiert Schwierigkeiten macht. Voll zustimm, das ist für Dich mehrere Nummern zu groß. Also erstmal: - LED an, - LED blinken mit Delay, - LED blinken mit Timer, - LED blinken mit Timerinterrupt, - LED mit Taste an/aus, - LED mit Taste toggle - 2 LEDs mit 2 Tasten toggle Dann bist Du bereit. Peter
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.