Hallo, wie kann ich eine globale Variable mit Hilfe eines Interrupts veränder, diese soll auch nach dem das Interrupt beendet ist den neuen wert behalten? Und wieso dauert die Abarbeitung des Interrupts ca 1-2 Sekunden? Mein Code #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> unsigned char level; void Init_Interrupt() { GICR|=(1<<INT0); MCUCR = (1<<ISC01) | (0<<ISC00); sei(); } ISR(_VECTOR(1)) { cli(); _delay_ms(50); level++; PORTB=~level; sei(); } int main() { unsigned char i; level = 0; Init_Interrupt(); while(1) { switch(level) { case 1: { ............ break; case 2: ......... break; default :{ level = 0; ... } ...
>unsigned char level;
volatile unsigned char level;
ISR(_VECTOR(1))
{ cli(); //rausschmeissen
_delay_ms(50); //Igitt!
level++;
PORTB=~level;
sei(); //rausschmeissen
}
danke, habs gerade auch im net gefunden :) habe aber noch eine Frage. Wieso dauert die Bearbeitung des Interrupts ca. 1-2 Sekunden? Mein Code #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> unsigned char level; void Init_Interrupt() { GICR|=(1<<INT0); MCUCR = (1<<ISC01) | (0<<ISC00); sei(); } ISR(_VECTOR(1)) { level++; } int main() { unsigned char i; level = 0; Init_Interrupt(); while(1) { switch(level) { case 1: { ............ break; case 2: ......... break; default :{ level = 0; ... } ...
es ist eher so dass nach dem interrupt das Hauptprogramm erst nach einer Verzögerung (ca. 1-2 Sekunden) weiter läuft. Wie kann man Taster bei einem Interrupt entprellen (ohne _delay_ms(...))?
Eugen V. schrieb: > es ist eher so dass nach dem interrupt das Hauptprogramm erst nach einer > Verzögerung (ca. 1-2 Sekunden) weiter läuft. Dem ist sicher nicht so, wenn Deine obige Interrupt-Routine mit der Wirklichkeit übereinstimmt. Du suchst an der falschen Stelle.
Hallo Eugen, was hältst Du davon, dem Vorschlag von Holger zu folgen und die Variable "volatile" zu deklarieren? Damit sagst Du dem Compiler, dass er nicht annehmen darf, dass die Variable den gleichen Wert behält, wenn er sie im Programmablauf nicht selbst verändert. Also muss er sie immer wieder neu aus dem Speicher laden, wenn er den aktuellen Inhalt haben will. Ist eine Variable nicht volatile, dann optimiert der Compiler alle Zugriffe auf die Variable außer dem ersten weg. Und wenn sich dann eine Schleife als bedeutungslos herausstellt, wird sie gleich mit wegoptimiert. Gruß Wolfgang
>was hältst Du davon, dem Vorschlag von Holger zu folgen und die >Variable "volatile" zu deklarieren? Das habe ich gemacht, habe leider vergessen es hier rein zu kopieren.
> Wie kann man Taster bei einem Interrupt entprellen (ohne _delay_ms(...))? Ich versuche mal eine Übersetzung: Du hast einen Taster an einem Pin (Input, Pullup/-down Widerstand, Taster gegen Ground/Vcc), und wenn man jenen Drückt, dann soll entprellt werden, sodass Du den Tastendruck eindeutig erkennen kannst? Falls das soweit stimmt: Entprellung Hierzulabor bevorzuge ich die Hardwareentprellung mit 1u und 15k, alles andere braucht (hier, für mich, und nur für mich gültig) zu viele Ressourcen, die anderweitig sinnvoller einzusetzen sind. Falls Du den µC hinreichend überdimensioniert hast, dann spricht nichts gegen eine Softwareentprellung. Die Details gibbet im Link :-) HTH
Namenlos schrieb: > Falls Du den µC > hinreichend überdimensioniert hast, dann spricht nichts gegen eine > Softwareentprellung. Das ist Quatsch, da muß man überhaupt nichts überdimensionieren. SW-Entprellung braucht max 4Byte SRAM, etwa 50Byte Code und kleiner 1% CPU-Leistung. Peter
Eugen, > es ist eher so dass nach dem interrupt das Hauptprogramm erst nach einer > Verzögerung (ca. 1-2 Sekunden) weiter läuft. wenn ich es richtig sehe, wird die ISR bei jedem Pegelwechsel angesprungen. Ein prellender Taster erzeugt reichlich Interrupts und die Variable wird häufiger inkrementiert, als Du eigentlich wünschst. Tschü Dude
> SW-Entprellung braucht max 4Byte SRAM, etwa 50Byte Code und kleiner 1% > CPU-Leistung. Ahja, und wo nimmst Du 4 Bytes SRAM und und 50 Bytes Flash her, wenn Du nix mehr übrig hast? Genau, du nimmst einen Controller, der hinreichend groß ist, vulgo einen größeren, als (ursprünglich) nötig. Mithin nennt man das 'überdimensionieren'. Ganz abgesehen von der Tatsache, dass man, ohne den CPU-Takt zu kennen (hat der TO was dazu geschrieben? falls ja dann hab ichs wahrscheinlich überlesen), lieber gaanz kleine Brötchen backen sollte. Ich hab hier z.B. einen Controller, der läuft mit knapp 1000Hz (ja, eintausend Hertz, nicht Kilo- und nicht Mega-, einfach nur Hertz). Da tut jeder vermeidbare ISR-Aufruf richtig weh. Von vergeudeten (Hardware)Timern ganz zu schweigen. Wie immer heisst die Devise: Der mündige Entwickler muss selbst entscheiden (jaja, ich weiss genau, was jetzt kommt: 'Die böse PR/Chefetage/Kosten-Leistungs-Vergleich/.. lässt mich nicht entscheiden'. Nixdan, wir sind hier im Hobbybereich, und da darf jeder mündige Entwickler eigene Entscheidungen treffen :-) was er braucht. Und anhand der gewünschten Ziele und der verfügbaren Hardware darf er dann eine Entscheidung treffen. ★Mir★ kommt keine Softwareentprellung ins Haus, weil ★ich★ mich als mündiger Entwickler bewusst für die Hardwareentprellung entschieden hab. Bei meinem nächsten Projekt sieht das möglicherweise ganz anders aus, aber da werde wieder ★ich★ entscheiden. Wenn ein anderer Entwickler was an ★seinem★ Projekt anders entscheiden will, dann nur zu. Wie so oft kann man nämliche keine allgemeingültige Antwort geben, was nun besser ist - der Kontext ist entscheidend. Reinzupflaumen > Das ist Quatsch ist jedenfalls völlig unangebracht.
Danke für die Beiträge, jetzt läufts auch :) Fand nur den letzten Beitrag leicht übertrieben :) Aber jedem das Seine!
1kHz (ich muss mich übrigens korrigieren: etwas über 1kHz, nicht knapp 1kHz..) ist ziemlich krass, ich weiss :-) Aber der Zweck heili^W^W^Wwenns anders nicht geht, dann muss mans nehmen, wies kommt.. :-) Wenn andererseits genug Ressourcen vorhanden sind (vulgo: hinreichend überdimensioniert ;-) dann spricht nix gegen Softwareentprellung. HTH und HF
Wenn der Datentyp "int" >8 bit ist (bei AVR ist er normalerweise 16 bit), dann erfolgen die Lesezugriffe in main nicht atomar, da der Prozessor immer nur 8 bit auf einmal verarbeiten kann. Der Vergleich im case wird daher z.B. zuerst das obere Byte und danach das untere Byte vergleichen und wenn beide gleich sind zum Ausführen der zugehörigen Anweisungen führen. Wenn dieser Ablauf zufällig durch einen Interrupt unterbrochen wird können unerwartete Effekte auftreten. War der Zähler z.B. 255 und es erfolgt ein Vergleich auf 0 könnte es so ablaufen: - high-byte wird verglichen, passt (beide 0) - Interrupt erhöht den Zähler auf 256 - low-byte wird verglichen, passt (beide 0) => das high-byte ist zwar inzwischen 1, wird jedoch nicht nochmal verglichen D.h. bei Datentypen >8bit auf einem 8-bit-Prozessor die in Interruptroutinen verändert werden können muss (bis auf wenige Ausnahmen, in denen man ganz genau wissen muss was man tut...) vor dem Auswerten im Hauptprogramm eine Interruptsperre erfolgen, die danach wieder aufgehoben werden kann. Man kann auch (wenn es der Verwendungszweck zulässt) einfach eine Kopie unter Interruptsperre erstellen und dann mit dieser Arbeiten. Alternativ wäre der Einsatz von 8-bit-Datentypen möglich, aber auch hier muss man etwas aufpassen, z.B. bei if((i>8)&&(i<7)) sollten die folgenden Anweisungen eigentlich nie ausgeführt werden, aber was, wenn i zuerst 9 war und mitten in der Prüfung auf 6 geändert wurde...
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.