Hallo zusammen,
ich hätte da nochmal eine Frage. Ich habe mich mühsam in Timer- und Interrupt-Programmierung reingefuchst und behaupte jetzt zu verstehen, was da passiert. Ich treibe den ganzen Aufwand, um präzise Sekunden messen zu können. Im Beispiel soll einfach nur eine LED im Sekundentakt blinken. Aber der Takt stimmt nicht - viel zu schnell!!!
Ich habe SO gerechnet:
Prozessortakt / Prescaler / Output Compare Registers = Interrupts pro Sekunde
mit Werten gefüllt:
1.000.000 / 8 / 125 = 1000 Interrupts pro Sekunde
Da nur geschaltet werden soll, wenn der counter == 1000 ist, müsste eigentlich nur einmal pro Sekunde umgeschaltet werden.
Hier mein Minimalbeispiel:
/*
* Dies ist ein kommentiertes Minimalbeispiel für einen
* Timer an einem Attiny85, der eine LED blinken lässt.
* Der uC ist mit 1MHz getaktet.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
volatile int counter;
void setup() {
/*
* Port B Data Direction Register - DDRB
* zuerst den output-Pin für eine LED festlegen (PB3):
*/
DDRB |= (1 << PB3);
/*
* CTC einschalten! Wenn die nächste Zeile
* auskommentiert wird, zählt der Timer immer bis
* 255 hoch und lässt sich natürlich dementsprechend
* schwer auf genaue Zeiten einstellen.
*/
TCCR0A = (1 << WGM01);
/*
* Prescaler auswählen und Einschalten des Timers
*/
// TCCR0B = (1 << CS00); // KEIN Prescaler
TCCR0B = (1 << CS01); // Prescaler clk/8
// TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler clk/64
// TCCR0B = (1 << CS02); // Prescaler clk/256
// TCCR0B = (1 << CS02) | (1 << CS00); // Prescaler clk/1024
/*
* Timer Interrupt Mask:
* Einschalten des Interrupts, so dass die Funktion ISR
* auch ausgeführt wird.
*/
TIMSK = (1 << OCIE0A);
/*
* Output Compare Registers:
* Speicher, in denen eine Zahl drinsteht.
* Erreicht der Timer (TCNT0) diese Zahl,
* findet der Overflow VOR 255 statt.
*/
OCR0A = 125;
}
ISR (TIM0_COMPA_vect)
{
counter++;
if (counter >= 1000)
{
/*
* Port B Data Register: Verwaltet alle In- und Outputpins (PB0-PB5)
* Durch das XOR "^=" wird PB3 umgeschaltet (HIGH wenn LOW und umgekehrt)
*/
PORTB ^= (1 << PB3);
counter = 0;
}
}
void loop(){
// tu nichts!
}
DIESE Seite ist mir bekannt, da wird vorgeschlagen den Timer selbst (TCNT0) zu modifizieren anstatt eine Obergrenze mit OCR0A = 125 zu setzen. Das ist mir unverständlich und es führt vor allem auch nicht zur genauen Sekunde!
Wo liegt mein Fehler?
Danke und Gruß, kuahmelcher
P.S.: Verbesserungsvorschläge zum Minimalbeispiel sind immer willkommen!!