Ich möchte auf Basis eines externe Events einen Timer Interrupt auslösen, der pro Event nur einmal durchläuft. Der Timer läuft für mehrere Millisekunden. Die externen Events passieren zyklisch in längeren Abständen und interferieren nicht mit dem Timerablauf. Verständnisfrage, kann ich ein "One Shot" Verhalten des Timers dadurch erreichen, das ich in der Timer ISR Routine das TOIEx Enable Bit von TIMSK auf Null setze, und beim nächsten Event TCNT und TOIEx wieder neu setze um den nächsten One Shot zu starten? Danke, Adrian
A. L. schrieb: > Ich möchte auf Basis eines externe Events einen Timer Interrupt > auslösen, der pro Event nur einmal durchläuft. Der Timer läuft für > mehrere Millisekunden. Die externen Events passieren zyklisch in > längeren Abständen und interferieren nicht mit dem Timerablauf. Die Formulierung ist dermaßen theoretisch, dass sie von einem Prof kommen könnte und nichts mit der Lösung eines realen Problems zu tun hat. Man könnte im Ext-Int den Timer initialisieren (also auf 0 setzen, Compare-Wert setzen, starten, Interrupt freigeben), so dass er beim Event startet. Im Timer-Compare-Int stoppt und deinitialisiert man den Timer wieder und löst die Reaktion aus. Müsste ich (für eigene Anwendung, nicht für den Prof) ein zum Event zeitversetztes Signal erzeugen, würde ich den Timer durchlaufen lassen, beim Event den Timerstand einlesen (wenn möglich per ICP), das Verzögerungsintervall draufaddieren und als Compare-Wert schreiben. Dann den Compare-Int initialisieren. Im Compare-Int dann die Reaktion auslösen und den Compare-Int wieder deaktivieren um weitere Aufrufe zu vermeiden. ...
Kein Prof, aber ich nehm das mal als Kompliment entgegen ;) Da ich zum Zeitpunkt des Postings noch keinen Code hatte, wollte ich das Problem möglichst generisch beschreiben. Die praktische Anwendung ist ein Treiber für ein Tacho Drehspulinstrument aus einem Siebziger Jahre Fahrzeug, für den das Original Tachotreiber IC nicht mehr erhältlich ist. Mittlerweile habe ich es ähnlich zu Deinem Vorschlag als CTC statt Overflow implementiert, und es funktioniert. Es war noch einen Fehler im Code, ich hatte über TIFR in der ISR Routine des Timers die ausstehenden Timer Interrupts zu löschen versucht, das hatte aber erst funktioniert nachdem ich TIFR |= 1<<OCF0A von der Timer ISR in die PCINT ISR verlagert habe. Danke für den Input! Source Auszug:
1 | int main(void) { |
2 | |
3 | ...
|
4 | // init pin change interrupt handler
|
5 | PCMSK |= (1<<PCINT1); |
6 | GIMSK |= (1<<PCIE); |
7 | |
8 | // config Timer0
|
9 | TCCR0B |= (1<<CS01); |
10 | TCCR0A |= (1<<WGM01); |
11 | OCR0A = 125; |
12 | |
13 | sei(); |
14 | |
15 | for(;;){ |
16 | }
|
17 | }
|
18 | |
19 | ISR(PCINT0_vect) { |
20 | //set Port to high
|
21 | PORTB |= (1<<PB2); |
22 | |
23 | // (re)start Timer0
|
24 | TCNT0 = 0; |
25 | TIFR |= (1<<OCF0A); |
26 | TIMSK |= (1<<OCIE0A); |
27 | }
|
28 | |
29 | ISR (TIMER0_COMPA_vect) { |
30 | // disable Timer0 Int (One Shot)
|
31 | TIMSK &= ~(1<<OCIE0A); |
32 | |
33 | //set Port to low
|
34 | PORTB &= ~(1<<PB2); |
35 | }
|
A. L. schrieb: > Die praktische Anwendung ist ein > Treiber für ein Tacho Drehspulinstrument aus einem Siebziger Jahre Also ein Monoflop. Das hättest Du mit dem NE555 auch hinbekommen. A. L. schrieb: > Mittlerweile habe ich es ähnlich zu Deinem Vorschlag als CTC statt > Overflow implementiert, Overflow hatte ich aber nicht empfohlen. Ich sprach von Compare-Interrupt und ggf ICP (Input-Capture-Interrupt, also ein externer Interrupt, der als Zugabe den Timerstand bereits beim Event sichert). Letzteres haben aber nicht alle AVR-Timer. CTC ist übrigens ein Spezialmodus des Compare-Interruptes. ...
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.