Hallo Leute, ich wollte anfangen mich mit der Programmierung von Mikrocontrollern zu beschäftigen. Dazu habe ich mir zu Beginn eine ganz einfache Schaltung zusammengebastelt. Die Schaltung findet ihr im Anhang. Die beiden Taster sollen lediglich die LEDs durchschalten. Damit wollte ich erstmal kontrollieren ob alles funktioniert und mich mit der Controller-Familie vertraut machen, bevor es an die größeren Projekte geht. Jetzt habe ich das Problem das, egal welchen der beiden Taster ich drücke, nur die ISR für INT1 aufgerufen wird. Hier der dazugehörige Quellcode: /*****************************************************************/ // #include Dateien /*****************************************************************/ #include <avr/io.h> #include <avr/interrupt.h> /*****************************************************************/ // Funktionen und Interrupt-Routinen /*****************************************************************/ void isr_init(void) { MCUCR |= 0b00001010; // Interrupts bei fallender Flanke GICR |= 0b11000000; // aktiviert INT0 und INT1 sei(); // aktiviert Global Interrupts } ISR(INT0_vect) // ISR für INT0 { PORTC = 0b00001010; } ISR(INT1_vect) // ISR für INT1 { PORTC = 0b00000101; } /******************************************************************/ // main /******************************************************************/ int main(void) { isr_init(); DDRC = 0x0F; PORTC = 0b00001110; while(1); return 0; } Habt ihr eventuell Ideen woran es liegen könnte? Schon mal Danke im Voraus :)
:
Bearbeitet durch User
Wenn Du die Taster per Interrupt auswerten möchtest (gleich geht das Gechreie wieder los), mußt Du sie anders verdrahten und auswerten. Beitrag "EIN-AUS mit Taster per Interrupt, ATtiny25 o.ä."
Aus dem Datenblatt des Prozessors: AVCC is the supply voltage pin for the A/D Converter, Port C (3..0), and ADC (7..6). It should be externally connected to VCC, even if the ADC is not used. If the ADC is used, it should be connected to VCC through a low-pass filter. Note that Port C (5..4) use digital supply voltage, VCC.
Wie schon angedeutet - Taster im Interrupt ist und bleibt Mist. Bringt nichts, macht nur Sorgen. Trotzdem scheint das Programm auf den ersten Blick richtig. Unschön die Schreibweise. Wenn man nicht ein Gedächtnis wie ein Elefant hat und diesem auch noch 100% vertrauen kann, kann man z.B. damit GICR |= 0b11000000; erstmal nicht viel anfangen ohen nachzuschlagen. GICR|=(1<<INT1) | (1<<INT0); ist selbsterklärend und weniger fehleranfällig (bei der binären Schreibweise kann schon mal ne Null fehlen :-) ) Bleibt noch die Hardware: 100n, die du mit einem Taster kurzschliesst, zerstören auf Dauer den Taster. Entweder noch einen Widerstand einfügen oder noch besser den Kondensator weglassen und die Tasten gescheit einlesen samt Softwareentprellung.
Danke schon mal für die schnellen Antworten. Wenn das Auswerten der Taster per Interrupts Mist ist, dann frag ich mich wie man sonst anständig Taster abfragt. Man kann es natürlich hier auch in die while-Schleife einfügen. Aber bei größeren Programmen, bei denen der Controller mehr zu tun hat, als in meinem kleinen Projekt hier, finde ich das ziemlich unschön. Mit der Schreibweise geb ich dir natürlich recht :) Mit der Softwareentprellung tue ich mich, ehrlich gesagt noch etwas schwer. Hab versucht mich zu dem Thema mal zu belesen, aber das scheint ja eine Glaubensfrage zu sein... Zu dem Hinweis mit dem AVCC, diesen hatte ich erstmal weggelassen, da ich weder den ADC noch die anderen Pins verwende. Bei den Pins(3..0) wird die Spannung durch den Controller ja lediglich auf GND gezogen.
Da M. schrieb: > ISR(INT0_vect) // ISR für INT0 > { > PORTC = 0b00001010; > } > > ISR(INT1_vect) // ISR für INT1 > { > PORTC = 0b00000101; > } Hallo, ich bin nicht unbedingt der Meinung, dass die Taster das ursprüngliche Problem sind... Meine Theorie ist eine andere. Ich bin da ja nun auch kein Profi, aber kann es sein, dass du bei keiner deiner Interupt-Routinen wieder zum Auslösepunkt zurückspringst? Wenn also INT0 ausgelöst wird, arbeitet er INT0 ab und danach direkt den danachfolgenden Befehl. Gab es dafür nicht den Befehl "Reti" oder so? Was passiert bei dir, wenn INT1 ausgelöst wird? Gruß Migelchen
:
Bearbeitet durch User
Da M. schrieb: > Zu dem Hinweis mit dem AVCC, diesen hatte ich erstmal weggelassen, da > ich weder den ADC noch die anderen Pins verwende. Bei den Pins(3..0) > wird die Spannung durch den Controller ja lediglich auf GND gezogen. AVCC ist die Versorgung des gesamten Ports, nicht nur der Ausgangstreiber. Das "should" in einem englischen Datenblatt hat die Bedeutung "muss". Migel C. schrieb: > Gab es dafür nicht den Befehl "Reti" oder so? Das macht der C-Compiler von sich aus.
Ich habe schon verschiedene Sachen durchprobiert. Ich habe die ISR einfach mal vertauscht: ISR(INT1_vect) // ISR für INT0 { PORTC = 0b00001010; } ISR(INT0_vect) // ISR für INT1 { PORTC = 0b00000101; } Aber auch hier springt er nur zu INT1, egal welche der beiden Tasten ich drücke. Auch habe ich in der main() die while schleife verändert um zu sehen ob er vielleicht in der ISR festhängt: while(1) { PORTC = 0b00001110; } Auch das sah gut aus. Er springt als auf jeden Fall aus der ISR wieder zurück zur main() Da ich jetzt nicht mehr weiter weiß, dachte ich, ich frag mal die Community :) Edit: ich werde nachher mal an AVCC 5V anlegen und schauen ob das was ändert
:
Bearbeitet durch User
Da M. schrieb: > Zu dem Hinweis mit dem AVCC, diesen hatte ich erstmal weggelassen, da > ich weder den ADC noch die anderen Pins verwende. Du musst ihn aber trotzdem speisen, denn wenn AVCC um mehr als ein paar zehntel Volt von VCC abweicht, ist das ein Verletzen der Specs. Wieviel genau die Abweichung sein darf steht im Datenblatt, und, wie o.a., auch der Hinweis, das man auf jeden Fall speisen muss. Wenn du den MC mit dem Strom verbindest, dauert es übrigens auch eine Weile, ehe die 100nF geladen werden, du hast also schon mal eine steigende Flanke. Zur Entprellung: https://www.mikrocontroller.net/articles/Entprellung Es gibt hard- und softwarebasierte Methoden. Wenn in der Software eh schon einer Timerinterrupt verwendet wird, bietet sich Software an.
Da M. schrieb: > Wenn das Auswerten der Taster per Interrupts Mist ist, dann frag ich > mich wie man sonst anständig Taster abfragt. In einem Timerinterrupt wird das gemacht. Man schaut sich in einem Timerinterrupt den zustand des Tasters an und wenn er mehrfach hintereinander derselbe war dann ist die Taste erkannt. Die Zeit zwischen zwei mal anschauen des Tasteneingangs sollte dabei groesser sein als die maximale Prellzeit des Tasters.
Noch ein Hinweis: Setzt doch das DDRD passend, so dass die beiden Taster Pins auch Eingänge sind. Im Sinne einer defensiven Programmierung ist das sinnvoll.
Ich denke, du hast eine Brücke zwischen D2 und D3. Egal, welchen Taster du drückst werden beide Ints ausgelöst und in der Reihenfolge Int0 dann Int1 abgearbeitet. NAch aussen scheint es, als ob nur Int1 aktiv war.
Also an deinem Programm liegt es sicher nicht. Hatte gerade einen Mega8 am Steckbrett und deine Schaltung getestet, funktioniert. Also solltest du mal deinen HW-Aufbau kontrollieren.
Helmut L. schrieb: >> Wenn das Auswerten der Taster per Interrupts Mist ist, dann frag ich >> mich wie man sonst anständig Taster abfragt. > > In einem Timerinterrupt wird das gemacht. Man schaut sich in einem > Timerinterrupt den zustand des Tasters an und wenn er mehrfach > hintereinander derselbe war dann ist die Taste erkannt. Die Zeit > zwischen zwei mal anschauen des Tasteneingangs sollte dabei groesser > sein als die maximale Prellzeit des Tasters. Ja das ist natürlich ne gute Idee. Darauf kam ich bisher nicht. Danke. Was ist denn so eine Standardzeit auf die man den Timerinterrupt setzen sollte? Ich hab mal irgendwo gelesen, dass ein Tastenprellen bis zu 10 ms dauert. Edit: Ich habe auch schon mal versucht mit dem Multimeter auf die Suche zu gehen. Eine Brücke ist da auf jeden Fall nicht zu finden. Habe auch geschaut ob bei einem Tastendruck an den Pins jeweils 0 V anliegt. Auch das sah gut aus. Bin mir eigentlich ziemlich sicher das der Aufbau korrekt ist... Oder zumindest wie in der oben gezeigten Schaltung ;) Ich werde dann eure Tipps nachher, wenn ich wieder zuhause bin, gleich ausprobieren und hoffen. Aber schon mal vielen Dank. Man merkt das ihr das schon etwas länger macht :P
:
Bearbeitet durch User
Da M. schrieb: > Ich werde dann eure Tipps nachher, wenn ich wieder zuhause bin, gleich > ausprobieren und hoffen. Ich an deiner Stelle würde in Int1 gar nichts machen, weil ich die Meinung von H.Joachim S. teile. Also, in main() periodisch die LEDs ausschalten (etwa 1 Mal/sec) und nur in Int0 etwas machen, dann siehst du auch gleich, ob die Routine angesprungen wird.
:
Bearbeitet durch User
Da M. schrieb: > Was ist denn so eine Standardzeit auf die man den Timerinterrupt setzen > sollte? Ich hab mal irgendwo gelesen, dass ein Tastenprellen bis zu 10 > ms dauert. Den kannst du natuerlich auch fuer weiter Sachen noch gebrauchen. Um irgendwelche Zeiten zu erhalten, um im Hintergrund LEDs zu flashen etc. Ich stelle den Timerinterrupt meisten auf 1ms. So kann man Softwaretimer mit aufloesungen von 1ms erhalten die dann an anderer Stelle im Programm gebraucht werden. Fuer die Tastenentprellung rufe ich dann z.B. nur bei jeden 10mal die Tastenabfrage auf (dann 10ms). Alles in einem Timerinterrupt.
Ich habe mir die Schaltung auch mal angesehen .... Die Kondensatoren an den Tastern.... Wieviel Strom müssen die Taster schalten? ;-) (rechne mal aus) Auf die Pullup kann man evtl. verzichten, die hat der AVR eingebaut. Und Strombegrenzungswiderstände, in Reihe zum Kondensator, ist sicher kein Fehler. Und seien es nur 100 Ohm Die Kondensatoren dämpfen einen Großteil des Prellens. Das Thema prellen ist damit schon quasi durch. Tasterabfrage: Ja, per Timer. Aber auch der INT kann Sinn machen, wenn man der AVR damit aus dem Tiefschlaf holen möchte. PCINT ist da auch eine gute Alternative, wenn es der AVR kann. Und ja, Avcc muss angeschlossen werden. Sonst drohen komische Erscheinungen. Auf die Induktivität kann man verzichten, wenn der ADC nicht genau (oder gar nicht) arbeiten muss, aber auf den Anschluss selber nicht.
So ich bin endlich dazu gekommen mich nochmal an die Schaltung zu setzen. Ich habe jetzt AVCC mit 5V verbunden und das DDRD Register für INT0 und INT1 auf Input zu setzen. Leider hat das keinen Erfolg gebracht. Hab dann auch mal die ISR, die ausgelöst wird, auskommentiert. Dann passiert gar nichts mehr. Also liegt es daran wohl auch nicht. Ich werd mich jetzt dran setzen und die Abfrage per Timer zu programmieren
:
Bearbeitet durch User
Miss doch erst mal mit einem Multimeter an den Eingängen ob die Pegel passen. Ich denke auch dass da ein Hardwarefehler vorliegt.
Das hab ich schon hinter mir. Bin jeden einzelnen Pin des Controllers abgegangen um zu schauen ob die gewünschte Spannung anliegt. Auch bei gedrückten Tastern. Alles wie es soll... Hab den Verdacht das der Controller vielleicht ne Macke hat :(
Da M. schrieb: > Hab den Verdacht das der Controller vielleicht ne Macke hat :( Das wäre natürlich auch noch eine Möglichkeit. Das Programm hat, wie schon geschrieben, keinen Fehler. Wenn man davon absieht das man Tasten besser mit Polling als mit einer ISR abfragt.
Da M. schrieb: > Verdacht das der Controller vielleicht ne Macke hat Das habe ich auch schon oft vermutet. Leider hat sich in der Praxis meist herausgestellt, dass der Fehler doch vor dem Bildschirm saß.
>Leider [...]
Kann man auch positiv sehen: Fehler in der Controllerhardware wären
wegen der praktischen Unmöglichkeit, sie zu korrigieren, schlimmer.
Ansonsten stimme ich Dir voll zu.
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.