Forum: Mikrocontroller und Digitale Elektronik Zeitgeber mit Timer0


von Marcel (Gast)


Lesenswert?

Hallöchen,

ich habe mir gerade mittels des Timer-Tutorials eine einfache Uhr 
geschrieben, aber irgendwie hat sie einen kleinen Versatz von ein paar 
ms pro 10s. Könntet ihr event. mal kurz drüberschauen, und berichten, wo 
das Problem sein könnte?

20 MHz;Timer0
1
void TIMER_INIT(void)
2
{
3
  // Konfiguration von 8-bit Timer/Counter0
4
  TCCR0B = (1<<CS01);    // Vorteiler:8
5
  TIMSK0 |= (1<<TOIE0);  // Aktivierung des Timer/Counter0-Overflow-Interrupts
6
7
  sei();          // Aktivierung der Interrupts auf globaler Ebene
8
}
9
/*******************************************************************************************************/
10
//Auswertung des Timer/Counter0-Overflow-Interrupts für den allg. Zeitgeber
11
ISR(TIMER0_OVF_vect)
12
{
13
  // 20000000/8/250(Frequenz;Vorteiler;Zählerschritte) = 10000 Takte pro Sekunde
14
  
15
  TCNT0 = 12; // Vorladen, um 250 Zählerschritte für einen genaueren Ausgangswert zu erreichen
16
17
  interruptCount++;
18
  if(interruptCount == 10)
19
  {
20
    timer_ms++;
21
    if(timer_ms == 1000)
22
    {
23
      dataCAN2 = 0;
24
      sendCAN();
25
26
      timer_s++;
27
      timer_ms = 0;
28
      if(timer_s == 60)
29
      {
30
        timer_m++;
31
        timer_s = 0;
32
      }
33
      if(timer_m == 60)
34
      {
35
        timer_h++;
36
        timer_m = 0;
37
      }
38
      if(timer_h == 24)
39
      {
40
        timer_h = 0;
41
      }
42
    }
43
    else if(timer_ms == 900)
44
    {
45
      dataCAN2 = 200;
46
      sendCAN();
47
    }
48
49
    interruptCount = 0;
50
  }
51
}


Viele Grüße,

Marcel

von Marcel (Gast)


Lesenswert?

Ps.:

Den Versatz habe ich bei TCNT0 = 5, die 12 zwar nur zu Testzwecken 
verändert wurden...

von Thomas E. (thomase)


Lesenswert?

Marcel schrieb:
> ISR(TIMER0_OVF_vect)
> {
>   // 20000000/8/250(Frequenz;Vorteiler;Zählerschritte) = 10000 Takte pro
> Sekunde
>
>   TCNT0 = 12; // Vorladen, um 250 Zählerschritte für einen genaueren
> Ausgangswert zu erreichen

Das taugt grundsätzlich nichts. Bis der Timer da angekommen ist, hat er 
schon wieder ein paar Schritte weitergezählt. Der bleibt in der ISR ja 
nicht bei 0 stehen.

>20 MHz;Timer0
Daraus schliesse ich mal, dass du einen moderneren Atmega hast, als den 
Atmega8 mit seinem 8048-Timer-Revival-Mode.
Der kann auch CTC mit Timer0. Damit kriegst du das exakt hin.

mfg.

von g457 (Gast)


Lesenswert?

> aber irgendwie hat sie einen kleinen Versatz von ein paar ms pro 10s

Ist Deine Taktquelle genauer als 10e-4?

Und: Steig auf einen CTC-Modus um, Overflow mit TCNT vorladen ohne 
spezielle Vorkehrungen ungenau.

von Marcel (Gast)


Lesenswert?

Hey Jungs,

danke für die schnellen Antworten. Ich werd' gleich mal nach dem CTC 
Mode schauen.

LG, Marcel

von Marcel (Gast)


Lesenswert?

Hi,

so, hab's jetzt mal so probiert...
1
TCCR0A = (1<<WGM01); // CTC Modus
2
TCCR0B |= (1<<CS01); // Prescaler 8
3
// ((1000000/8)/1000) = 125
4
OCR0A = 125-1;
5
 
6
// Compare Interrupt erlauben
7
TIMSK0 |= (1<<OCIE0A);
8
9
sei();
10
    timer_ms++;
11
    if(timer_ms == 1000)
12
    {
13
      dataCAN2 = 0;
14
      sendCAN();
15
16
      timer_s++;
17
      timer_ms = 0;
18
      if(timer_s == 60)
19
      {
20
        timer_m++;
21
        timer_s = 0;
22
      }
23
      if(timer_m == 60)
24
      {
25
        timer_h++;
26
        timer_m = 0;
27
      }
28
      if(timer_h == 24)
29
      {
30
        timer_h = 0;
31
      }
32
    }

Mein Problem ist jetzt nur, dass das Beispielprogramm mit 1 MHz F_CPU 
rechnet und so mit dem Vorteiler auf eine gerade Zahl im 8bit-Bereich 
kommt.
Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125. Wie 
kann ich denn mit dieser Zahl OCR0A steuern?

Liebe Grüße,

Marcel

von Marcel (Gast)


Lesenswert?

Hallöchen,

hat denn niemand einen Rat?

LG, Marcel

von spess53 (Gast)


Lesenswert?

Hi

>Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125.

Es sind es 77,125.

>Wie kann ich denn mit dieser Zahl OCR0A steuern?

Nach 7 Interrupts den OCR-Wert auf 78 erhöhen und beim nächsten 
Interrupt wieder auf 77 setzen.

Oder einen 18,432MHz Quarz nehmen.

MfG Spess

von Thomas E. (thomase)


Lesenswert?

Marcel schrieb:
> Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125. Wie
> kann ich denn mit dieser Zahl OCR0A steuern?
20.000.000 / 64 = 312500
OCR0A = 249
312500 / (OCR0A + 1) = 1250

ISR(TIMER0_COMPA_vect)
{
  static int nTimerCT = 0;
  nTimerCt++;

  if(nTimerCt == 1250)
  {                            //1s
    nTimerCt = 0;

mfg.

von Marcel (Gast)


Lesenswert?

Guten Abend allerseits,

vielen lieben Dank an euch beide.

Ich habe Spess' Weg gewählt, da ich sonst wohl noch einen Zähler für die 
Anpassung auf Millisekunden bräuchte.

Es scheint einwandfrei zu funktionieren... ;




Einen wundervollen Abend,

Marcel

von Marcel (Gast)


Lesenswert?

Ps.:

Hey Spess,

es scheint ja soweit zu gehen, aber ich würde gern noch verstehen 
warum.;-)
Ich komm irgendwie nicht dahinter...

Viele Grüße,

Marcel

von spess53 (Gast)


Lesenswert?

Hi

>es scheint ja soweit zu gehen, aber ich würde gern noch verstehen
>warum.;-)
>Ich komm irgendwie nicht dahinter...

8 x 77,125  = 617

Geht aber nicht da es nur ganzzahlige Takte gibt. Deshalb

7 x 77 + 78 = 617

MfG Spess

von Marcel (Gast)


Lesenswert?

... und ich hab über eine Stunde die wildesten Gleichungen 
aufgestellt.;-)

Vielen lieben Dank und einen ganz wundervollen Tag noch.

Marcel

von Marcel (Gast)


Lesenswert?

Hey,

das bedeutet dann aber auch, dass ich eine auf die ms zugreifende 
Applikation nur alle 8 ms (bzw. Zyklen) um die 125 Takte synchronisieren 
kann?

LG, Marcel

von spess53 (Gast)


Lesenswert?

Hi

>das bedeutet dann aber auch, dass ich eine auf die ms zugreifende
>Applikation nur alle 8 ms (bzw. Zyklen) um die 125 Takte synchronisieren
>kann?

Welche '125 Takte'?

Du hast 7 mal eine 'Millisekunde' die 0,162% zu kurz sind und eine 
'Millisekunde' die 1,134% zu lang ist. Damit mußt du leben oder einen 
geeigneten Quarz einsetzen.

MfG Spess

von amateur (Gast)


Lesenswert?

Deine Uhr geht die meiste Zeit minimal vor und korrigiert sich mit dem 8 
Takt.
Wenn Dir das nicht passt hilft nur ein passender Quarz. Die sind meist 
problemlos zu haben, bewirken aber meist, dass der Rechner etwas 
langsamer läuft. Also 18,?? statt 20MHz oder 14,?? statt 16 MHz.
Eine weitere Möglichkeit ist, Du schaust Dir mal den Artikel: "Die 
genaue Sekunde" an

von Marcel (Gast)


Lesenswert?

Hi,

danke, ich werd' mir das mal anschauen.



LG, Marcel

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.