Forum: Mikrocontroller und Digitale Elektronik Countdown-Timer Interrupt wird nach Aktivierung ausgelöst


von Wolfgang K. (Firma: Neutron Mikroelektronik GmbH) (wollekette)


Lesenswert?

Hallo alle zusammen,

ich verwende einen ATtiny1634 Baustein, um ein bestimmtes Protokoll auf 
Basis der UART Schnittstelle zu implementieren.

Dabei möchte ich nach einem Ereignis (Startbit bei UART erkannt) eine 
definierte Zeit warten und danach eine Aktion auslösen.

Für die Zeit habe ich den Timer1 so konfiguriert, dass er jeweils nach 
270µs auslöst.
1
TCCR1B  = (1<<WGM12);    // Clear Timer on Compare Match
2
TCCR1B |= (1<<CS11);     // Prescaler 8
3
OCR1A   = 269;           // Liefert bei 8MHz ein 270us Intervall

Im Interrupt, der bei Erkennung eines Startbits ausgelöst wird, starte 
ich den Timer
1
ISR(USART0_RXS_vect)
2
{
3
    TCNT1  = 0;           // Counter auf 0 setzen
4
    TIMSK |= (1<<OCIE1A); // Compare Interrupt erlauben
5
}

Im zugehörigen Timer Interrupt deaktiviere ich den Compare Interrupt 
wieder
1
ISR(TIMER1_COMPA_vect)
2
{
3
    TIMSK  &= ~(1<<OCIE1A);   // Compare Interrupt deaktivieren
4
    ...
5
}

Mein Problem ist jetzt, dass der Compare-Interrupt jedes mal direkt 
ausgelöst wird, nachdem er aktiviert wurde. Also direkt nach dem 
USART0_RXS_vect.


Natürlich kann ich jetzt immer den ersten Interrupt ignorieren, aber 
dass kann's ja wohl nicht sein. Außerdem verstehe ich es nicht. Ich hab 
auch schon versucht, direkt vor oder nach Aktivierung des Timers das 
Output-Compare-Flag OCF1A zu löschen. Hab ich aber entweder nicht 
richtig gemacht oder es hat nichts genutzt.

Kann mir da bitte jemand helfen bzw. es erklären?

von Peter D. (peda)


Lesenswert?

Wolfgang K. schrieb:
> Außerdem verstehe ich es nicht.

Du verbietest nur die Ausführung des Handlers, das Pending-Bit ist davon 
völlig unberührt. Es wird gesetzt, wenn die Bedingung erfüllt ist. Und 
wenn Du später den Handler erlaubst, wird er natürlich ausgeführt.

Wolfgang K. schrieb:
> Hab ich aber entweder nicht
> richtig gemacht oder es hat nichts genutzt.

Kleine Gemeinheit von Atmel, Pending-Bits löscht man durch Setzen. In 
diese Fallgrube tappt jeder Programmierer mal.
Nebenfallgrube daraus:
Setzen darf man nicht mit OR, da dann alle Pending-Bits im selben 
Register mit gelöscht werden. Man darf daher nur mittels Zuweisung oder 
AND löschen.

Andere Möglichkeit: Du kannst den Timer auch einfach anhalten.

von Route_66 H. (route_66)


Lesenswert?

Peter D. schrieb:
> Setzen darf man nicht mit OR, da dann alle Pending-Bits im selben
> Register mit gelöscht werden. Man darf daher nur mittels Zuweisung oder
> AND löschen.

Das verstehe jetzt wer will. Gerade mit OR wird doch nur das 
betreffende Bit gesetzt, und alle anderen bleiben unbeeinflusst!

von Thomas E. (thomase)


Lesenswert?

Route 6. schrieb:
> Das verstehe jetzt wer will. Gerade mit OR wird doch nur das
> betreffende Bit gesetzt, und alle anderen bleiben unbeeinflusst!

Das ist eine Read-Modify-Write Operation. Das Byte wird also gelesen, 
bearbeitet und wieder geschrieben.

Steht z.B. 0000 0011 drin und du veroderst mit 0000 0001, weil du Bit0 
löschen willst, wird danach 0000 0011 drauf geschrieben. Und das löscht 
beide Bits. Schreibst du direkt 0000 0001 drauf, wird nur Bit0 gelöscht.

Ist halt kein normales Register.

von Route_66 H. (route_66)


Lesenswert?

Thomas E. schrieb:
> Ist halt kein normales Register.

Jetzt hab ichs verstanden.
Das Bit wird duch die Interruptanforderung gesetzt und durch erneutes 
Setzen gelöscht.
Wer denkt sich sowas aus?

von Wolfgang K. (Firma: Neutron Mikroelektronik GmbH) (wollekette)


Lesenswert?

Danke an alle für die Beiträge,

der Vorschlag mit dem Anhalten des Timers von Peter Dannegger war für 
mich die Lösung.

Ich hatte zwar auch schon daran gedacht, war aber irgendwie der Meinung, 
man könne die Timer nicht unabhängig voneinander anhalten. Weiß auch 
nicht, wie ich darauf kam. Dabei muss man ja nur den Prescaler 
entsprechend setzen.

Vielen Dank auf jeden Fall

von Thomas E. (thomase)


Lesenswert?

Wolfgang K. schrieb:
> Ich hatte zwar auch schon daran gedacht, war aber irgendwie der Meinung,
> man könne die Timer nicht unabhängig voneinander anhalten. Weiß auch
> nicht, wie ich darauf kam

So abwegig ist das nicht. Das GTCCR-Register dient genau dazu: Beide 
Timer gleichzeitig zu stoppen, den Prescaler zurück zu setzten und beide 
Timer synchron zu starten.

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
Noch kein Account? Hier anmelden.