Am besten geht das in einem Timer.
Hier mal eine Routine zum Initialisieren, aus dem Wiki zusammengeschnitzt:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
// Werte zur Berechnung der Interrupt-Rate bei AVR-Fuses,
// die auf 1MHz eingestellt sind (Werkseinstellung für internen RC-Oszillator)
#define F_CPU 1000000 // 1 MHz
// Prototypen der Funktion(en)
void timer1_init (uint16_t);
// Initialisiert Timer1, um mit einer Frequenz von freq IRQs auszulösen
void timer1_init (uint16_t freq)
{
// ATmega: Mode #4 für Timer1 und voller MCU-Takt (Prescale=1)
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS10);
// OutputCompare1A Register setzen
OCR1A = (uint16_t) ((uint32_t) F_CPU / freq -1);
// OutputCompare1A Interrupt aktivieren
TIMSK |= (1 << OCIE1A);
}
// Die Interrupt Service Routine (ISR) wird mit
// der Frequenz freq ausgeführt.
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
// mach was
}
void main()
{
timer1_init (1000);
sei();
while (1);
}
Für klassische AVRs wie AT90S2313 muss die Initialisierung etwas abgeändert werden, weil sich Bit-Bezeichner unterscheiden:
Code:
// AVR Classic:
// Timer1 läuft mit vollem Takt
// CTC: Clear Timer on CompareMatch
// Timer1 ist Zähler
TCCR1A = 0;
TCCR1B = (1 << CS10) | (1 << CTC1);
Lesezeichen