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.
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.
Sobald Deine CPU-Frequenz (mit obiger Formel) größer als 8,388608 MHz ist, läuft Dir außerdem OCR1A über (Max. 65535).
>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.
>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.
Tobias, vergiss was ich da geschrieben habe. Hab das mit dem SPI Port ducheinander gebracht. Sorry. Daz
Ö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.
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
Ähm nö, ich hab WGM12 gesetzt, also sollte CTC (Timer Mode 4; siehe S. 111) laufen und bei OCR1A auf Null fallen...
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
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?
Muss ich dazu ein spezielles Register setzen oder läuft das standardmäßig ohne Ausgabe?
Klar, ist ne Frage der Pin Konfiguration (Seite 109). Aber das aendert nix an der Interrupt-Frequenz.
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?
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.