Forum: Compiler & IDEs Frequenz vom Timer


von Tobias G. (tobster)


Lesenswert?

Ich versuche mit der folgenden Timerkonfig die Frequenz von einem Hz auf
einem ATMEGA16 zu erzeugen. Der Interruppt wird auch aufgerufen, aber
wesentlich öfter als einmal pro Sekunde. Die Formel stammt aus dem
Datenblatt von Seite 100.

    // CLK/64 Prescaler, Lösche Counter bei compareA match

    TCCR1B = (1<<CS10) | (1<<CS11)  | (1<<WGM12);
    OCR1A = ((F_CPU/2/64)-1);    // hier sollte jetzt 1 Hz rauskommen
    TIMSK = (1<<OCIE1A);      // Output Compare-Interrupt aktivieren
  sei();              // Globale Ints aktivieren

Sieht jmd hier einen entscheidenden Fehler, warum da mehr als 1 Hz
generiert wird? Ich hab irgendwie mittlerweile ein Blackout.

von The Daz (Gast)


Lesenswert?

Die Formel auf Seite 100 bezieht sich auf fclk_io, die halb so hoch wie
die CPU Frequenz ist. Dein Timer müsste also im 2Hz Takt ticken.

von Der Nachrechner (Gast)


Lesenswert?

Sobald Deine CPU-Frequenz (mit obiger Formel) größer als
8,388608 MHz ist, läuft Dir außerdem OCR1A über (Max. 65535).

von Tobias Gärtner (Gast)


Lesenswert?

>Die Formel auf Seite 100 bezieht sich auf fclk_io,
>die halb so hoch wie die CPU Frequenz ist

Achso, wo steht denn diese Falle beschrieben, das ich das übersehen
hab? Muss ich heute Abend mal testen, indem ich einfach nochmals durch
Zwei teile... Erst mal Danke, an dieser Stelle.

Das mit dem 8 Mhz sollte kein Thema darstellen, da nur ein 7,3
MHz-Quarz  angeschlossen ist.

von Der Nachrechner (Gast)


Lesenswert?

>indem ich einfach nochmals durch Zwei teile...

eben NICHT, sondern mit zwei multiplizieren.
Dann reduziert sich der maximal Takt aber auf 4,194... MHz
==> den Vorteiler vergrößern.

von The Daz (Gast)


Lesenswert?

Tobias,
vergiss was ich da geschrieben habe. Hab das mit dem SPI Port
ducheinander gebracht. Sorry.

  Daz

von Tobias Gärtner (Gast)


Lesenswert?

Öh, jetzt bin ich verwirrt... Also fclk_io ist nicht die Hälfte von
F_CPU? Also muss ich weder halbieren, noch verdoppeln? Dann müsste es
ja funktionieren... Hm.

von The Daz (Gast)


Lesenswert?

Tobias,
ich denke dein Problem beruht auf einem Missverstaendnis. Die Formel
gilt fuer den CTC mode des timers, dein Timer laeuft aber im normal
mode (oder ?). Da wird der Timercounter mit F_CPU hochgezaehlt. Das
heisst bei 7.3MHz und einem Teiler 64 kommst du in einer Sekunde auf
ca. 114.000 ticks. Da dein Zaehler aber nur 16 bit breit ist und damit
nur bis 65535 zaehlt dauert es nur 0.57 Sekunden bis zum Ueberlauf,
wass dann 1,7 Hz entspricht.

  Daz

von The Daz (Gast)


Lesenswert?

Und genau das hat Nachdenker in seinem posting gemeint.

von Tobias Gärtner (Gast)


Lesenswert?

Ähm nö, ich hab WGM12 gesetzt, also sollte CTC (Timer Mode 4; siehe S.
111) laufen und bei OCR1A auf Null fallen...

von The Daz (Gast)


Lesenswert?

Man, ich sollte mir ne Brille kaufen. Hast Recht. Allerdings : Die
Formel gilt fuer die Berechnung der Signal-Frequenz am OC1A pin. Im
Diagramm siehst du aber auch, dass jedesmal wenn der counter den OCR1A
Wert erreicht ein interrupt generiert wird und der output getoggelt
wird. Fuer einen output toggle cycle muss also zwei Mal der counter
durchlaufen und dabei zwei interrupts generieren. Lange Rede : kurze
Sinn : du bekommst interrupts mit 2Hz wenn dein OC1A Signal 1 Hz hat.

  Daz

von Tobias Gärtner (Gast)


Lesenswert?

OK, kann man das ganze eigentlich auch so anstellen, das man komplett
ohne die Ausgabe auf dem Pin auskommt, also den Pin weiterhin als IO
benutzen kann?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, natürlich.

von Tobias Gärtner (Gast)


Lesenswert?

Muss ich dazu ein spezielles Register setzen oder läuft das
standardmäßig ohne Ausgabe?

von The Daz (Gast)


Lesenswert?

Klar, ist ne Frage der Pin Konfiguration (Seite 109). Aber das aendert
nix an der Interrupt-Frequenz.

von Tobias G. (tobster)


Lesenswert?

Leute, ich häng an dem Problem einfach fest: Ich habe den Prescaler
jetzt am Maximum von 1024 und die Formel (von der ich eigentlich
annehmen muss, das sie stimmt) NICHT verändert. Ich habe also nicht den
tatsächlichen Prescalerwert eingesetzt, sondern rumeperimentiert und
kleinere Werte genommen, um die Interrupts zu drosseln. Es stimmt aber
hinten und vorne nicht.

Ich hab mich auch zig mal versichert, das der Quarz wirklich nur 7,3
MHz hat. Woran liegt es, das das einfach nicht hinhaut und da 1 Int /
Sekunde generiert wird?

von Hubert.G (Gast)


Lesenswert?

Wenn du den takt durch 64 teilst kommt 114062 raus. Das heist der
Counter zählt in einer Sekunde bis 114062. In den OCR1A schreibst du
aber 57031 hinein (laut Rechnung) daher sollte der Takt der herauskommt
dann 0,5 sek sein. Soweit ich das in der Schnelligkeit überblicke.

Prescaler 256 und in OCR1A F_CPU/256 dann sollte in etwa das richtige
herauskommen. Genau ist es nicht, da müsste der Quarz genau teilbar
sein.

Hubert

von Tobias G. (tobster)


Lesenswert?

Problem ist gelöst, zwar unschön per Trial'n'Error aber wenigstens hab
ich jetzt ungefähr ne Sekunde. Hier die neuen Codezeilen, wobei ich
immernoch nicht genau verstanden hab, warum das genau so jetzt geht
(vgl. ersten Post):

    TCCR1B = (1<<CS12) | (1<<WGM12);
    OCR1A = ((F_CPU/256)-1);    // 1 Hz für den Interrupt

von Michael N. (e-lektroniker)


Lesenswert?

Das ganze hab ich auf einem AT 90S8515 getestet.
Müste aber im Prinzip auf jeden Typ laufen.
(Timer anpassen)
int main(void)
{
TCCR1B = (1<<CS10) | (1<<CS11);   //setzt den Prescaler 64
OCR1A = 62500;                    //setzt den Vergleichswert
TCNT1 = 0;                        //startewert des Counters
TIMSK = 1<<OCIE1A;                //Compare-Int aktivieren
sei();                            //globale Ints aktivieren
}

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
 //wird ausgeführt wenn der Counterwert mit dem Vergleichswert
übereinstimmt
  // Uhrenroutine
  s++;  // s jede Sekunde um 1 erhöhen
  TCNT1 = 0; //timer 1 auf null

for (;;)
{Programm}
}

OCR1A = 62500;  errechnet mit der Formel:

OutpurCompare = Fosc/prescaler * Tsoll
z.B.:
OCR1A = 4000000Mhz/64 * 1 = 62500

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.