mikrocontroller.net

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


Autor: Guido S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
    // Timer soll durchlaufen er löst keinen Int aus und wird nicht zurückgestellt
    // Timer 1 einstellen - Timer wird als CTC genutzt
        // Mode 4
        // CLKi/o / 1   oder   CLKi/o / 8
    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
    OCR1A = 0xFFFF;        // bis hier wird gezählt
    TCCR1A = 0; 
    #if (F_CPU <= 6553500)
    TCCR1B = (1 << WGM12) | (1 << CS10); 
    #else
    TCCR1B = (1 << WGM12) | (1 << CS11); 
    #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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
{
}

Autor: Guido S. (Gast)
Datum:

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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann ebend so:

ISR(TIMER1_CAPT_vect)
{

}

ISR( TIMER1_OVF_vect)
{

}

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder du stellst beim COMP TCNT1 noch einmal neu ein

Autor: Guido S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: He Ro (Gast)
Datum:

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

MfG, HeRo

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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."

Autor: Guido S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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.

ISR (TIMER1_COMPA_vect)
{
  OCR1A += DELAY_A;
}

ISR (TIMER1_COMPB_vect)
{
  OCR1B += DELAY_B;
}



Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Guido S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.