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);