#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h> // Required for ISRs and sei()
int main(void)
{
// --- SETUP ---
// 1. Set built-in LED (PB5) as an OUTPUT
DDRB |= (1 << DDB5);
// 2. Set Timer1 Mode to "Normal" (overflow at 0xFFFF)
TCCR1A = 0x00; // WGM10 and WGM11 are 0
TCCR1B = 0x00; // WGM12 and WGM13 are 0
// 3. Set Prescaler to 1024
// CS12=1, CS11=0, CS10=1
TCCR1B |= (1 << CS12) | (1 << CS10);
// 4. Set the Preload Value for 1 second
// 65535 - 15625 = 49910
TCNT1 = 49910;
// 5. Enable the Timer1 Overflow Interrupt
// TIMSK1 (Timer/Counter1 Interrupt Mask Register)
// TOIE1 (Timer/Counter1 Overflow Interrupt Enable)
TIMSK1 |= (1 << TOIE1);
// 6. Enable Global Interrupts (Master Switch)
sei();
// --- LOOP ---
// The main loop is empty! The CPU is free.
// It could be reading sensors, updating an LCD, etc.
while (1)
{
// Do other work...
}
}
// --- INTERRUPT SERVICE ROUTINE ---
// This function is called AUTOMATICALLY every 1 second
ISR(TIMER1_OVF_vect)
{
// 1. Toggle the LED
// Using XOR (^) is a fast way to flip the bit
PORTB ^= (1 << PB5);
// 2. IMPORTANT: Reload the preload value
// The timer reset to 0 after overflowing, so we must
// set it back to 49910 for the *next* 1-second interrupt.
TCNT1 = 49910;
}