www.mikrocontroller.net

Forum: Compiler & IDEs Frequenz vom Timer


Autor: Tobias Gärtner (tobster)
Datum:

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

Autor: The Daz (Gast)
Datum:

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

Autor: Der Nachrechner (Gast)
Datum:

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

Autor: Tobias Gärtner (Gast)
Datum:

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

Autor: Der Nachrechner (Gast)
Datum:

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

Autor: The Daz (Gast)
Datum:

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

  Daz

Autor: Tobias Gärtner (Gast)
Datum:

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

Autor: The Daz (Gast)
Datum:

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

Autor: The Daz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und genau das hat Nachdenker in seinem posting gemeint.

Autor: Tobias Gärtner (Gast)
Datum:

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

Autor: The Daz (Gast)
Datum:

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

Autor: Tobias Gärtner (Gast)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, natürlich.

Autor: Tobias Gärtner (Gast)
Datum:

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

Autor: The Daz (Gast)
Datum:

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

Autor: Tobias Gärtner (tobster)
Datum:

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

Autor: Hubert.G (Gast)
Datum:

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

Autor: Tobias Gärtner (tobster)
Datum:

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

Autor: Michael Neumann (e-lektroniker)
Datum:

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

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.