Gast
#594834
Guten Morgen,
Meine Frage:
ich arbeite seit ein paar Wochen an einer Schaltuhr für die
Gartenbewässerung. Der Teil "Digitaluhr" funktioniert und geht auch sehr
genau (Abweichung ~1s in 72 Stunden). Diese Genauigkeit reicht für
meinen Anwendungsfall aus.
Ich habe nun erfolglos versucht den Code umzustellen und die Berechnung
der Uhrzeiten, Datum etc. in die Interupt-Routine zu schieben. Dabei
beobachte ich, dass die Laufzeit des Timers sich ändert, d.h. die mit
dem Zähler gemessene Zeit zwischen 2 High-Flanken an Pin5 (siehe
Interupt-Routine) ändert sich, wenn ich im if-Zweig der Interupt-Routine
Kommandos hinzufüge!!!
Meiner Erwartung nach, dürfte sich da aber nichts ändern solange ich
unter 40000 Taktyklen bleibe...
Was ist los? Habe ich den Timer falsch benutzt ? Stimmt der Mode?
Oder habe ich was übersehen ?
Die Fakten:
Dazu verwende ich dieses Konstrukt (ich hab die relevanten Teile
rauskopiert) und compiliere es fehlerfrei mit GCC:
#define F_CPU 4000000UL // Takt in Hertz
#define T_VAL 39974 // Mit Zähler abgeglichen auf 1,0000043s
ISR(TIMER1_COMPA_vect)
{
OCR1A = T_VAL;
TCNT1=0;
tri_cnt++;
if (tri_cnt>99) {
trigger=1;
tri_cnt=0;
//Debug 1.0000043s
PORTC |= (1<<PC5);
asm("nop");
PORTC &= ~(1<<PC5);
}
}
Im main wird der Timer so initialisiert:
TCCR1A = 0x00;
TCCR1B = 1<<WGM12 ^ 1<<CS10; // set CTC-Mode "4" + no prescaler
OCR1A = T_VAL;
TCNT1 = 0;
TIMSK = 1<<OCIE1A;
sei();
Alle 10ms wird in die Interupt-Routine gesprungen und der Timer neu
initialisiert (dies müsste doch Peters "Genaue Sekunde" entsprechen.
Danach wir der Zähler "tri_cnt" so lange erhöht bis er 100 ist. Die
Variable "trigger" verwende ich im Moment als Flag um im Hauptprogramm
die Uhrenberechnung und die Ausgabe aufs LCD zu steuern.
Gruß
Andreas