Forum: Mikrocontroller und Digitale Elektronik TIMER1 durchlaufend Interrupt zu verschiedenen Zeiten ATMega8


von Guido S. (Gast)


Lesenswert?

Hallo!

Wie bekomme ich einen durchlaufenden Timer, der Interrupts zu 
verschiedenen Zeiten auslösen kann?
Ich habe Timer1 so programmiert, dass er durchläuft. Er beginnt bei 
0x0000 und zählt bis 0xFFFF. Dieser soll nicht verändert werden, da er 
als Zeitbasis für verschiedene Dinge dient.
Nun möchte ich erreichen, dass bei einem bestimmten Zählerstand ein 
Interrupt ausgelöst wird. Dies soll aber nicht bewirken, dass der Zähler 
zurückgesetzt wird.
Wie bekomme ich das hin?

Hier ein kleiner Ausschnitt aus meinem Programm:
1
    // Timer soll durchlaufen er löst keinen Int aus und wird nicht zurückgestellt
2
    // Timer 1 einstellen - Timer wird als CTC genutzt
3
        // Mode 4
4
        // CLKi/o / 1   oder   CLKi/o / 8
5
    TCNT1 = 0;      // Timer soll von 0 beginnen; dieser Befehl ist eigentlich nicht notwendig, da es egal ist, wo der Zähler beginnt, hier ist er nur zur Veranschaulichung
6
    OCR1A = 0xFFFF;        // bis hier wird gezählt
7
    TCCR1A = 0; 
8
    #if (F_CPU <= 6553500)
9
    TCCR1B = (1 << WGM12) | (1 << CS10); 
10
    #else
11
    TCCR1B = (1 << WGM12) | (1 << CS11); 
12
    #endif

Da OCR1A auf 0xFFFF gestellt ist, würde hier der Interrupt ausgelöst 
werden. Ich möchte aber den Interrupt früher auslösen und der Zähler 
soll weiterlaufen bis 0xFFFF.

Danke und Gruß
Guido

von gast (Gast)


Lesenswert?

wie wärst mit 2 isr routinen:
ISR(TIMER1_OVF_vect)   //Interrupt bei Overflow Timer1
{
}

ISR (TIMER1_COMPA_vect)   //Interruppt bei compare je nach OCR1A
{
}

von Guido S. (Gast)


Lesenswert?

Gute Idee. Klappt aber leider nicht, da bei Erreichen von COMPA der 
Timer TCNT1 auf 0x0000 gestellt wird und damit OVF nie erreicht.

von gast (Gast)


Lesenswert?

dann ebend so:

ISR(TIMER1_CAPT_vect)
{

}

ISR( TIMER1_OVF_vect)
{

}

von gast (Gast)


Lesenswert?

oder du stellst beim COMP TCNT1 noch einmal neu ein

von Guido S. (Gast)


Lesenswert?

Die letzte Variante, dass ich TCNT1 neu einstelle, wenn COMPA-Int 
ausgelöst wird, geht zwar, ist aber nicht so sauber. Besonders in C habe 
ich das Problem, dass schon viele Takte vergangen sind, bevor der erste 
Befehl der ISR abgearbeitet wird. Bei Vorteiler 8 sind es immerhin 5 
Zähler. Das kann ich kaum kompensieren.
Ich suche noch eine elegantere Lösung.

von Matthias Kölling (Gast)


Lesenswert?

Was baust Du eigentlich, dass 5 Prozessortakte ein Problem sind?
Wenn die unterschiedlichen Zeiten nicht "parallel" sondern nacheinander 
gebraucht werden hätte ich es mit dem Compare Interrupt gemacht und das 
Compareregister in der ISR neu geschrieben. Ich hatte noch nie den Fall, 
dass das ein Problem darstellt. Wenn es ohne Zeitverzug sein soll ist 
das eher ein Fall für einen CPLD oder FPGA.

Gruß Matthias

von He Ro (Gast)


Lesenswert?

Wenn du den Timer richtig einstellst, wird er eben nicht gelöscht, wenn 
OCR1A/OCR1B erreicht wird.

MfG, HeRo

von Karl H. (kbuchegg)


Lesenswert?

Guido S. wrote:
> Gute Idee. Klappt aber leider nicht, da bei Erreichen von COMPA der
> Timer TCNT1 auf 0x0000 gestellt wird

Seit wann?
Die Atmel Doku zum Mega16 scheint das noch nicht zu wissen.
Dort ist mit keinem Wort erwähnt, dass bei einem Compare Match
der Counter wieder auf 0 gesetzt wird.

(Was du meinst ist der CTC Modus. Der ist hier aber nicht gemeint.
Es spricht nichts dagegen, einen durchlaufenden Timer zu haben,
der mittels der Output Compare Unit bei einem beliebigen Zaehler-
stand einen Interrupt auslöst)

von Gast (Gast)


Lesenswert?

einfach das WGM12 (CTC1) nicht setzen (vgl. Tutorial):
"Wenn dieses Bit gesetzt ist, so wird nach einer Übereinstimmung des 
Datenregisters TCNT1H/TCNT1L mit dem Vergleichswert in OCR1H/OCR1L das 
Datenregister TCNT1H/TCNT1L auf 0 gesetzt."

von Guido S. (Gast)


Lesenswert?

Na Kollegen, ich stelle doch eine solche Frage nicht ohne Grund. Ich 
habe Hilfe erwartet. Vielleicht bin ich zu dumm oder es ist mit dem 
ATMega8 nicht realisierbar.

@Matthias Kölling

> Was baust Du eigentlich, dass 5 Prozessortakte ein Problem sind?

Ob 5 Takte ein Problem sind, kann ich noch nicht sagen. Die 5 Zähler des 
Timers bei Vorteiler 8, was immerhin 40 Takte sind, können schon bei 
einfachen Anwendungen ein Problem sein, wenn die CPU nur mit 1 MHz 
getaktet wird.
Was ich hier mache, kann ich auch verraten. Es soll ein 
Phasenabschnittsdimmer mit Infrarotfernbedienung werden. Mein Ehrgeiz 
war es, nur einen Timer zu verbraten. Es sollen dann auch 2 Verbraucher 
mit einem µC gedimmt werden. Ich glaube, ich werde die anderen Timer 
auch mit einbeziehen und hoffentlich mehr Erfolg haben.

@Re Ho
> Wenn du den Timer richtig einstellst, wird er eben nicht gelöscht, wenn
> OCR1A/OCR1B erreicht wird.

Das glaube ich. Aber ich benötige Hilfe, wie ich es einstellen kann.

@kbuchegg
> (Was du meinst ist der CTC Modus. Der ist hier aber nicht gemeint.
> Es spricht nichts dagegen, einen durchlaufenden Timer zu haben,
> der mittels der Output Compare Unit bei einem beliebigen Zaehler-
> stand einen Interrupt auslöst)

Ja ich spreche von CTC. Jedenfalls habe ich MODE 4 eingestellt, wie du 
aus meinem Programmausschnitt sehen kannst.
Aber mir dämmert, vielleicht sollte ich einen PWM-Modus wählen. Dort 
habe ich dann aber das Problem, dass ich nicht die volle Distance bis 
65536 zählen kann. Oder kann ich doch?

@Gast
> einfach das WGM12 (CTC1) nicht setzen

Wenn ich das mache, dann ist der Timer aus. Davon habe ich auch nichts.

Gruß
Guido

von OliverSo (Gast)


Lesenswert?

>Nun möchte ich erreichen, dass bei einem bestimmten Zählerstand ein
>Interrupt ausgelöst wird.

A) Warum?
b) Warum?
c) Warum?

Anstatt aus der einen ISR rauszuspringen, nur um dann in eine andere ISR 
reinzuspringen, lass doch in der einen Timer-ISR einen Zähler mitlaufen, 
und wenn der abgelaufen ist, führe irgendwas zusätzlich aus. Ganz ohne 
die ISR's zu wechseln. Das koste dich zwar in jedem ISR-Duchlauf ein 
paar Takte für den Zähler un die Abfrage, aber wenn es schon daran 
scheitert, hats du eh andere Probleme.

Oliver

von Peter D. (peda)


Lesenswert?

Guido S. wrote:
> Die letzte Variante, dass ich TCNT1 neu einstelle, wenn COMPA-Int
> ausgelöst wird, geht zwar, ist aber nicht so sauber. Besonders in C habe
> ich das Problem, dass schon viele Takte vergangen sind, bevor der erste
> Befehl der ISR abgearbeitet wird. Bei Vorteiler 8 sind es immerhin 5
> Zähler. Das kann ich kaum kompensieren.

Mußt Du auch nicht, der Timer zählt ja weiter.
Einfach im Compareinterrupt den nächsten Comparewert setzen.
1
ISR (TIMER1_COMPA_vect)
2
{
3
  OCR1A += DELAY_A;
4
}
5
6
ISR (TIMER1_COMPB_vect)
7
{
8
  OCR1B += DELAY_B;
9
}


Peter

von Karl H. (kbuchegg)


Lesenswert?

Guido S. wrote:

> Ja ich spreche von CTC.

Und ich frage mich, warum du da überhaupt irgendeinen
anderen Modus als den ganz normalen Zähler-zählt Modus nimmst?

> Aber mir dämmert, vielleicht sollte ich einen PWM-Modus wählen.

Wozu?


> @Gast
>> einfach das WGM12 (CTC1) nicht setzen
>
> Wenn ich das mache, dann ist der Timer aus.

Quatsch. Der Timer zählt, sobald ein Vorteiler eingestellt ist.
Das WGM12 Bit hat damit nichts zu tun.

von Guido S. (Gast)


Lesenswert?

@kbuchegg

WGM12 habe ich jetzt nicht gesetzt. Und siehe da, kaum macht man es 
richtig, schon funktioniert es. Jetzt läuft der Zähler durch, wie 
gewünscht. Nun stimmt auch meine Zeitbasis.

Großen Dank!!!
Guido

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.