Zeitgeber mit Timer0

Gast #3294840
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
#3294857
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.
Gast #3294863
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.
Gast #3294908
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
Gast #3295581
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
Gast #3296398
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
Gast #3296601
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
Gast #3296772
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
Gast #3296797
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren