Wozu dann überhaupt eine ISR? Dann kannst du ja gleich das Interrupt Status Bit in der Mainloop pollen.
MfG Klebwax
Druckbare Version
auch nach vielen versuchen und änderungen will der code nicht. jetzt wird zu langsam gezählt :(
was mache ich nur falsch?Zitat:
#include <avr/interrupt.h>
...
unsigned long int timerLauf= 0;
...
int main (void)
{
TCCR1B |= (1<<CS02) | (1<<CS00);
OCR1A = 15625;
TIMSK |= (1<<OCIE1A);
sei();
...
}
ISR (TIMER1_COMPA_vect)
{
timerLauf++;
}
Hast du den Quarz richtig eingestellt?
Setzt du den Timer auch wieder zurück nachdem der ISR aufgerufen wurde?
Du musst noch ins Register TCCR1B das Bit CTC aktivieren -> Clear Timer on Compare Match -> Rücksetzen nach Abgleich ;)
Wahrscheinlich zählt der Timer 1 mal richtig und dann zählt er immer die vollen 65535 Schritte durch
Also ca so:
Timerwert: 0...........15625 *INTERRUPT* ..............65535 - 0 ........ 15625 *INTERRUPT* ...........65535 - 0 .........15625 *INTERRUPT*.... ->
Zeiterlauf: 0s.................1s............................. ...................................4,2s........... ............................................8,4s.. ................. ->
Variable:...0....................1................ .................................................. 2................................................. ...........3.................... ->
wenn ich das CTC aktiviere lässt sich der code nicht kompilieren :(
error: 'CTC' undeclared (first use in this function)Zitat:
TCCR1B |= (1<<CTC) | (1<<CS02) | (1<<CS00);
achja: quarz ist richtig eingestellt (getestet mit _delay_ms(xx) -> funktioniert exakt, auch gemessen mit dem oszi)
Wie genau meinst du das?
Setzt du den Timer auch wieder zurück nachdem der ISR aufgerufen wurde?
Ok...
CTC heißt das der Timer nach dem Match - also der Übereinstimmung - zurückgesetzt wird
Das kannst du aber auch händisch machen inem du in deiner ISR den Timer wieder auf 0 zurück setzt:
Code:TCNT1=0; //Timer-Wert-Register auf 0 setzen
Ohne CTC läuft der Timer nicht richtig.
Das CTC bedeutet, das das TCNT1 Register bei einem Comparematch auf 0 gesetzt wird.
Wenn das nicht eingestellt ist wird der Timer über den Overflow springen und dann erst wieder beim Zählerstand von 15625 wieder einen Interrupt auslösen.
Das bedeutet der Interrupt wird nur alle ca 4 Sekunden angesprungen.
Da gibt es mehrere Lösungen.
Entweder du zählst bei einem aufgetretenen Comparematch Interrupt ( in diesem natürlich ) einfach die 15625 zum Comparematchwert dazu.
OCR1A+=15625;
Das bewirkt, das beim Zählerstand von 31250 wieder ein Interrupt ausgelöst wird.
Keine Angst bei den Überläufen ( >65535 ) Werden die Überlaufenden Bits gekillt, weil das ja nur ein 16Bit Register ist.
Oder du aktivierst das CTC Bit im Register, das anscheinend in der Library anders heisst, oder nicht definiert ist.
Guck auch mal ins Datenblatt unter Timer 1 WGM10 bis WGM13 bzw. CTC1.
Das mit dem TCNT1=0 würde ich nicht machen, weil dabei ein kompletter Zählersprung "vergessen" werden könnte und deine Uhr damit auf Dauer falsch geht.
Das ist halt eine Sache wie lange deine Controller sich in anderen Interupts aufhält, wie lange diese Interrupts sind und welche Prescaler man benutzt.
danke für eure antworten. kann im moment leider nichts testen - werde den code aber noch versuchen und mich dann nochmals melden ;).
so. nach einigen tests von beiden beschriebenen beiträgen muss ich leider wider einen misserfolg vermelden. es will und will nicht :(.
Wie macht sich den der Fehler bemerkbar?
Wird die Timer-ISR nicht ausgeführt oder was?
Weder ein syntaktisch noch ein semantisch Fehler wird vom Compiler angezeigt, folgedessen muss es sich um einen Logikfehler handeln.
Bemerkbar macht sich das dadurch, dass der Couter jetzt gar nicht mehr hochzählt.
folgenden code verwende ich im moment:
laut meinem verständnis sollte der code jede sekunde unterbrechen und den zähler "Laufvariable" durch die isr um eins erhöhen. ist der zähler über 100 gekommen, so wird er reseted.Zitat:
//Variablen initialisierung
long int Laufvariable = 0;
//HAUPTPROGRAMM
int main (void)
{
//Timer1 (16Bit) Initialisieren
TCCR1A |= (1<<CS02) | (1<<CS00) | (1<<WGM10);
OCR1A = 15625;
TIMSK |= (1<<OCIE1A);
sei();
...
...
//Ausgabe der Variablen "Laufvariable" auf dem Display
//(Displayfehler habe ich 100%ig ausgeschlossen)
...
...
return 0;
}
//INTERRUPT von Timer1 (16Bit)
ISR (TIMER1_COMPA_vect)
{
if (++Laufvariable > 100)
Laufvariable = 0;
}