Zeitgeber mit Timer0

Gast #3294840
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
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
> 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
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
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
#3295637
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.
Gast #3296398
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 #3296588
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
Gast #3296601
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 #3296700
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
Gast #3296772
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
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

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.