Hallo! Ich verwende den ATtiny44 und über den PCINT0 wird eine ISR bei positiver Flanke ausgelöst und eine AD-Wandlung durchgeführt. Wird ein Interrupt ausgelöst, springt mein Debugger nach Ausführung der ISR nochmals in die ISR. Erst danach wird das Programm weiter ausgeführt. Hat jemand einen Tip was da sein könnte?
H. G. schrieb: > Hat jemand einen Tip was da sein könnte? Ja, Deine (jede) Taste prellt. Deshalb Tasten nie mit einem externen Interrupt abfragen! Sondern mit einem Timerinterrupt entprellen. Peter
H. G. schrieb: > Ich verwende den ATtiny44 und über den PCINT0 wird eine ISR bei > positiver Flanke ausgelöst und eine AD-Wandlung durchgeführt. > Wird ein Interrupt ausgelöst, springt mein Debugger nach Ausführung der > ISR nochmals in die ISR. Erst danach wird das Programm weiter > ausgeführt. Bei einem PCINT kann man nicht vorgeben, ob er bei einer steigenden oder fallenden Flanke aufgerufen wird. Er wird in jedem Fall bei beiden Flanken aufgerufen. > Hat jemand einen Tip was da sein könnte? Wenn obiges nicht zutrifft, muss es an der Zeile 42 in Deinem Programm liegen ;-)
Ggf. den Interupt in der ISR beim ersten Aufruf erstmal deaktivieren und mit einem Timer nach n ms wider aktivieren, wenn der PCINT nicht noch andere Pins abfragen muss die während der Deaktivierungszeit eintreffen könnten. Dann hätte man auch das Tastenentprellen mit erledigt.
Peter Dannegger schrieb: > ...Sondern mit einem Timerinterrupt entprellen. Hallo Peter! Ich habe mir deine Komfortroutine etwas angesehen, aber das ist natürlich ein overkill für eine einzige Taste welche am PCINT0 hängt. Hast du ein Beispiel mit einem Timer Interrupt in C für eine Taste?
H. G. schrieb: > Ich habe mir deine Komfortroutine etwas angesehen, aber das ist > natürlich ein overkill für eine einzige Taste welche am PCINT0 hängt. Das ist so wenig Code, das ist selbst für nur eine Taste effizient. Den Repeat-Teil kann man ja weglassen, wenn man ihn nicht benötigt. Peter
H. G. schrieb: > Hast du ein Beispiel mit einem Timer Interrupt in C für eine Taste? Der nächste Software-Guttenberg. Und was er kopieren kann ist ihm nicht einfach genug, deshalb fragt er nach etwas noch einfacherem... Ohne Worte
Ich habe jetzt versucht, gleich am Anfang der ISR alle Interrupts zu deaktivieren und nicht wieder zu aktivieren. Trotzdem springt der Debugger ein 2. Mal rein. ??? Kann ja normal nicht sein, oder? Hier meine ISR:
1 | // *********** Pin change INT0 service routine *************
|
2 | ISR (PCINT0_vect) |
3 | {
|
4 | cli(); |
5 | ADMUX &= !(1<<MUX0); // Auf ADC-Kanal 0 umschalten |
6 | |
7 | ADCSRA |= (1<<ADSC); // Start ADC-Converter |
8 | while (ADCSRA & (1<<ADSC)); // wait for ADC-Conversion |
9 | x = ADC; // Dummy read out |
10 | |
11 | ADCSRA |= (1<<ADSC); // Start ADC-Converter |
12 | while (ADCSRA & (1<<ADSC)); // wait for ADC-Conversion |
13 | switch_value2 = ADC; // Value for endswitch |
14 | |
15 | ADCSRA |= (1<<ADSC); // Start ADC-Converter |
16 | while (ADCSRA & (1<<ADSC)); // wait for ADC-Conversion |
17 | switch_value3 = ADC; // Value for endswitch |
18 | |
19 | switch_value = (switch_value2 + switch_value3) / 2; // ADC Durchschnittswert berechnen |
20 | |
21 | if ( (switch_value >= 849) && (switch_value <=988) ) // 4,15V ... 4,8V |
22 | {
|
23 | ES1 = 1; |
24 | ES2 = 0; |
25 | }
|
26 | |
27 | if ( (switch_value >= 661) && (switch_value <=767) ) // 3,23V ... 3,75V |
28 | {
|
29 | ES2 = 1; |
30 | ES1 = 0; |
31 | }
|
32 | |
33 | ADMUX |= (1<<MUX0); // Auf ADC-Kanal 1 umschalten |
34 | |
35 | ADCSRA |= (1<<ADSC); // Start ADC-Converter |
36 | while (ADCSRA & (1<<ADSC)); // wait for ADC-Conversion |
37 | x = ADC; // Dummy read out |
38 | |
39 | //sei();
|
40 | }
|
Udo Schmitt schrieb: > H. G. schrieb: >> Hast du ein Beispiel mit einem Timer Interrupt in C für eine Taste? > > Der nächste Software-Guttenberg. > Und was er kopieren kann ist ihm nicht einfach genug, deshalb fragt er > nach etwas noch einfacherem... > Ohne Worte Ich fragte nach einem Beispiel und nicht nach einem fertig angepassten Code! Ist dir langweilig oder warum müllst du das Forum mit solch unqualifizierten Ansagen voll? Oder darf man hier im Forum nicht fragen? Ist das ein Forum nur für Profis? Anfänger raus?
H. G. schrieb: > Hier meine ISR: Un du machst dir Sorgen um die 20 (Assembler-)Instruktionen (auf die der C-Code hinausläuft) in der PeDa Entprell-Lösung?
H. G. schrieb: > Kann ja normal nicht sein, oder? Doch, denn das Sperren der Interrupts (und gesperrt sind sie in der ISR sowieso, dein cli() macht also in Wirklichkeit gar nichts) hat keinen Einfluss darauf, dass beim Eintreffen eines Ereignisses das entsprechende Interrupt-Flag gesetzt wird.
20? Da hab ich dann wohl ein anderes Beispiel angesehen! Hast du einen Link?
H. G. schrieb: > Kann ja normal nicht sein, oder? Doch, siehe Abschnitt: 4.8 Reset and Interrupt Handling Es gäbe da einen dirty Hack: direkt vor dem Enable das Interruptflag setzen. Peter
H. G. schrieb: > 20? > > Da hab ich dann wohl ein anderes Beispiel angesehen! > Hast du einen Link? Auf wieviele Assembler Instruktionen läuft das wohl im Compiler raus.
1 | ISR( TIMER0_OVF_vect ) // every 10ms |
2 | {
|
3 | static uint8_t ct0, ct1, rpt; |
4 | uint8_t i; |
5 | |
6 | i = key_state ^ ~KEY_PIN; // key changed ? |
7 | ct0 = ~( ct0 & i ); // reset or count ct0 |
8 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
9 | i &= ct0 & ct1; // count until roll over ? |
10 | key_state ^= i; // then toggle debounced state |
11 | key_press |= key_state & i; // 0->1: key press detect |
12 | |
13 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function |
14 | rpt = REPEAT_START; // start delay |
15 | if( --rpt == 0 ){ |
16 | rpt = REPEAT_NEXT; // repeat delay |
17 | key_rpt |= key_state & REPEAT_MASK; |
18 | }
|
19 | }
|
Den Aufwand in der ISR kannst du vernachlässigen, das kostet deinen µC weniger als 1% Rechenzeit. Und das geile ist: Das funktioniert von 1 bis 8 Tasten ohne Codeänderung. Selbst bei 1 Taste lohnt sich der Code schon, weil die Entprellung zuverlässig funktioniert und du keinen Tastendruck deines Benutzers verpasst. Und einen Auto-Repeat der bei gedrückter Taste dem Programm weitere Tastendrücke vorgaukelt, kriegst du automatisch mit dazu (besonders cool bei Zahleneingaben mittels Up-Down einzusetzen) Oft genug bewährt, oft genug eingesetzt. Es lohnt ganz einfach nicht, sich da auch nur den geringsten Gedanken über eine andere Lösung zu machen. Dieses Ding ist in 10 Minuten in einen Code integriert und funktioniert bullet-proof.
stammt von Entprellung Lass dich nicht von der Anzahl der C Zeilen blenden. Entscheidend ist, was nach dem Compilieren übrig bleibt. Und das ist nicht viel.
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.