Forum: Mikrocontroller und Digitale Elektronik Timerberechnung die hunderste


von Christop (Gast)


Lesenswert?

Hallo,

ich verstehe die Berechnugn des Timers einfach nicht.

Also ich will einen Timer der möglichst genau 1 sek betrifft.

Mein ATMega128 läuft auf 16 Mhz externen Quarz.
1
void timer_init(void) {
2
3
  TCCR1B = (1<<CS10) | (1<<CS12);  // Timer mode with 1024 prescler
4
  TCNT1 = 15625;   // for 1 sec at 16 MHz
5
  TIMSK = (1 << TOIE1) ;   // Enable timer1 overflow interrupt(TOIE1)
6
  sysTimer = 0;
7
  sysTimerReloadValue = 10000;
8
9
}

und die ISR
1
ISR (TIMER1_OVF_vect)    // Timer1 ISR
2
{
3
  TCNT1 = 49911;   // for 1 sec at 16 MHz
4
  if (sysTimer > sysTimerReloadValue) {
5
    sysTimer = 0;
6
  }
7
  sysTimer++;
8
}

1 sek ensprechen vll 300ms...

Was mache ich falsch?

von A. S. (Gast)


Lesenswert?

Wie stellst Du fest, wie lange es dauert? Wenn es 250ms sind, dann ist 
es ein Faktor 4.

Warum eigentlich bis 10001? Eigentlich ist es am einfachsten, den 
durchlaufen zu lassen, dann braucht man keine Sonderbehandlung für 
Überlauf.

von Christian S. (roehrenvorheizer)


Lesenswert?


von Christop (Gast)


Lesenswert?

der fehler ist/war... weil ich in der ISR TCNT auf einen falsch wert 
gesetz habe.

von H.Joachim S. (crazyhorse)


Lesenswert?

Warum benutzt du nicht den CTC-Modus? Der genau für sowas gedacht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christop schrieb:
> der fehler ist/war... weil ich in der ISR TCNT auf einen falsch wert
> gesetz habe.
Das Problem ist, dass du den Zähler überhaupt änderst. Denn was 
passiert, wenn da ein höherpriorer Interrupt zuvorkommt und der Timer 
inzwischen schon weiter gezählt hat, als er es "normalweise" tut? Dann 
hast du Zeit verloren, deine Uhr geht nach.

H.Joachim S. schrieb:
> Warum benutzt du nicht den CTC-Modus? Der genau für sowas gedacht.
Bei dem läuft der Timer nämlich immer stur geradeaus durch, egal ob ein 
anderer Interrupt dazwischenkommt.

: Bearbeitet durch Moderator
von MaWin (Gast)


Lesenswert?

Christop schrieb:
> Was mache ich falsch?

Ähm, alles.

Nutze einen Timer-Mode, der von selbst rücksetzt.

Beachte, dass ein 16MHz Quartz keine 16.000000MHz liefert, kleine 
Abweichungen sind also sowieso möglich, üblich sind +/-50ppm also 
+/-800Hz, eine Korrektur im Sub-1Hz-Bereich ist überflüssig

von Christop (Gast)


Lesenswert?

Also das ist der einzigste Interrupt der überhaupt genutzt wird.. einzig 
und alleine der timer..

es gibt keine weiteren interrupts...

egal was ich mache...

es bleibt bei 3 sek.


ja.. nehm ein CTC.. ich hänge an dem timer jetzt seit wochen.. ohne 
erfolg...

es muss auch nicht genau sein... es muss nur immer ungefähr jede sek 
hoch gezählt werden...

so das z.b.

if ( (sysTimer % 10) == 0 )

{
  uart_puts().......
}

also das ungefair alle 10 sek der uart output kommt...

da kommt es jetzt nicht drauf an ob das 9.5 oder 10.5 also es sollte 
ungefair passen...

modulo 3 eben ungefair alle 3 sek...

und module 1 eben jede sek (so ungefair) aber nicht wie jetzt

if ( (sysTimer % 1) == 0 ) {
  uart_puts("Timer Interrupt");
}

und die ausgabe kommt derzeit "ungefair" alle 3 sek... aber nicht mal 
annähernd bei 0,8 - 1,5 sek....

von Peter D. (peda)


Lesenswert?

Christop schrieb:
> if ( (sysTimer % 1) == 0 ) {
>   uart_puts("Timer Interrupt");
> }

Ah ja, nochn Schnipselchen.
Wie wärs, wenn Du mal nen echten, exakten Code anhängen würdest.

Bei dem Schnipselchen würde ich erwarten, daß immer jede 2. Sekunde lang 
die UART den Text mehrmals raushaut.

von Oliver S. (oliverso)


Lesenswert?

Christop schrieb:
> es bleibt bei 3 sek.

Zeig doch mal das ganze Programm. Zumindest der erste Interrupt kommt 
schon mal wegen der falschen TCNT-Initialisierung erst nach 3,2s. Wer 
weiß, wie der ganze Rest aussieht.

Oliver

von Christop (Gast)


Angehängte Dateien:

Lesenswert?

Ok, ich habe jetzt einfach mal den gesamten Code angehangen....

Der Timer wird aber nur in der main.c und in der timer.c genutzt.. der 
rest hat mit dem Timer nichts zu tun...

Aber jetzt der vollständige Code..

von Peter D. (peda)


Lesenswert?

Nicht Dein Ernst?
Wenn Du das Timerproblem lösen willst, dann hau den ganzen anderen 
Schrunz erstmal aus.
Und wo steht denn das nicht funktionierende:
1
if ( (sysTimer % 1) == 0 ) {
2
  uart_puts("Timer Interrupt");
3
}
?

von Christop (Gast)


Angehängte Dateien:

Lesenswert?

In den Code, habe ich gerade geschaut.. steht nur noch meine test var...

ich habe nochmal den Code.. wie ich es zuletzt getestet habe 
angehangen..

was habe ich geädert?

Also ich habe das if ..... aus der ISR entfernt und gegen
1
///// SYSTEMTIMER TEST
2
    
3
if ( test != sysTimer ) {
4
   uart_puts("Timer Interrupt");
5
   test = sysTimer;
6
}

in der while ersetzt.

von Oliver S. (oliverso)


Lesenswert?

Peter D. schrieb:
> Nicht Dein Ernst?
> Wenn Du das Timerproblem lösen willst, dann hau den ganzen anderen
> Schrunz erstmal aus.

So ist es.
Bau ein Testprogramm nur aus Timerinitiaisierung und ISR, mit einem 
minimalen main, und stell das hier ein. Dann schauen wir weiter.

Oliver

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.