AVR (ATMega328P) Timer mal wieder zu langsam (~2Sec / Min)

OP #4074283
Lesenswert?

Hallo,

ich habe mich auch mal an das Projekt DCF77 gewagt.
Bis die Zeit Synchronisiert wird lasse ich sie via Interrupt hoch 
zählen.
Dazu habe ich mir eine kleine Timerklasse geschrieben, die mir dabei 
helfen soll.
Jetzt habe ich allerdings bemerkt, dass meine Uhr ca. 2 Sekunden pro 
Minute zu langsam läuft und ich habe noch keine Idee warum.
Mein uC läuft mit 16MHz.

Timer2, der den 1ms-Interrupt erzeugt:
1
  //1ms Interrupt
2
  TCNT2  = 0;
3
  OCR2A  = (250 - 1);    // so gibt das 1ms - Pulse
4
  TCCR2A  = 0;        //Pins nicht verbunden, aber Clear Timer on Compare match (CTC) mode
5
  TCCR2B  = ( 1 << CS22);    //Prescaler 64
6
  TIMSK2  = ( 1 << OCIE2A);  //Timer/Counter2, Output Compare A Match Interrupt Enable

Interrupt-Routine:
1
ISR( TIMER2_COMPA_vect)
2
{
3
  GetTimerHelper().Interrupt1ms();
4
}

main:
1
    while(1)
2
    {
3
    GetTimerHelper().Process();    
4
    }

Wrapper für die globale Variable
1
CTimerHelper& GetTimerHelper()
2
{
3
  static CTimerHelper TimerHelper;
4
  return TimerHelper;
5
}

Inhalt Interruptroutine
1
void CTimerHelper::Interrupt1ms()
2
{
3
#if TIMER_SUPPORT_1MS
4
  do1ms++;
5
#endif
6

7
  ms++;
8

9
  if( ms % 10 == 0) do10ms++;
10
  #if TIMER_SUPPORT_100MS
11
  if( ms % 100 == 0) do100ms++;
12
  #endif
13
  if( ms >= 1000) {
14
    do1s++;
15
    ms = 0;
16
  }
17
}

Hat jemand eine Idee, wo ich schauen könnte?
Wenn ihr den Code kurz testen wollt geht das ganz einfach:
1
class ctest : CTimer
2
{
3
//hier eigenen code rein
4
 void Timer1s(){}
5
 void Timer10ms(){}
6
 void Timer100ms(){}
7
} test;

ggf müsst ihr noch diesen codeschnipsel vorher einfügen, dass alles 
klappt:
1
extern "C" {
2
  void __cxa_pure_virtual()
3
  {
4
    uart_puts_P( "ERROR!\n\r-->__cxa_pure_virtual\n\r");
5
    // put error handling here
6
  }
7
}


Auch wenn der Funktionsansprung etwas dauern sollte, der Timer2 läuft 
doch außerhalb des Programms weiter. D.h. die Zeit die dadurch verlohren 
wird sollte sich nicht auswirken, da der Interrupt dann einfach früher 
kommt.
Habt ihr eine Idee? Danke schon mal!
Angehängte Dateien:
Gast #4074415
Lesenswert?

Spiffman G. schrieb:
> Habt ihr eine Idee? Danke schon mal!

Ich weiss nicht bei welchem Prozessor ich nachschauen soll, aber
wenn nicht der CTC Mode eingestellt ist dann müsstest du deinen
Timer in der ISR "von Hand" zurücksetzen. Selbst dann gibt es
noch eine kleine zeitliche Verwerfung.

Und wenn dein Timer 8 Bit gross ist: ein Faktor 256/250 ist
ungefähr 62/60.
#4074453
Lesenswert?

Spiffman G. schrieb:
> Timer2, der den 1ms-Interrupt erzeugt:

und warum?

reicht für DCF77 nicht 10ms muss der IRQ nicht so oft angesprungen 
werden.

OK ich nutze meist IRMP und dort sind es 64µs IRQs aber ein mitlaufender 
Zähler macht dann alle 10ms die Verzweigung in die DCF77 Abfrage sowie 
Tastenabfragen nach Dannegger.

Alle 10ms mal nach dem DCF Bit reicht doch, ist entweder 100ms oder 
200ms aktiv und das kann man mitzählen.
OP #4078348
Lesenswert?

Joachim B. schrieb:
> Spiffman G. schrieb:
>> Timer2, der den 1ms-Interrupt erzeugt:
>
> und warum?
>
> reicht für DCF77 nicht 10ms muss der IRQ nicht so oft angesprungen
> werden.
>
> Alle 10ms mal nach dem DCF Bit reicht doch, ist entweder 100ms oder
> 200ms aktiv und das kann man mitzählen.

So kann ich den Vorteiler mit dem 8-Bit Timer geschickt wählen. Bei 
16MHz komm ich ganzzahlig auf 1ms. Daher teile ich quasi in der Software 
noch mal durch 10 und sample dann das DCF77 Signal alle 10MS

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