🛠 Programmer aux registres : interruption Timer/Counter1
Objectives
Move beyond the Arduino API to drive the ATmega32u4 "bare metal": configure Timer/Counter1 in CTC mode (Clear Timer on Compare Match) with a prescaler of 1024, trigger a hardware interrupt at 1 Hz, and toggle the LED on pin 13 (PB7) directly via the PINB register. You will understand the complete path: 16 MHz clock, prescaler, OCR1A, interrupt vector, and why an ISR must remain minimal.
Hardware
- 1 Arduino Leonardo (the sketch runs on top of the Arduino core, which remains necessary for initialization and the Caterina bootloader)
- No external components: the built-in LED is sufficient
Complete Code
// Clignotement 0,5 Hz par interruption Timer/Counter1 en mode CTC
// 16 MHz / 1024 (prescaler) / 15625 = 1 Hz d'increment compare
volatile uint8_t clignotements = 0;
void setup {
DDRB |= (1 << DDB7); // PB7 (Arduino D13) en sortie
noInterrupts;
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10); // mode CTC, prescaler 1024
TCNT1 = 0;
OCR1A = 15624; // 16e6 / 1024 / (15624+1) = 1 Hz
TIMSK1 |= (1 << OCIE1A); // autorise l'interruption Compare Match A
interrupts;
}
ISR(TIMER1_COMPA_vect) {
PINB = (1 << PINB7); // ecriture de 1 dans PINB = bascule la broche
clignotements++;
}
void loop {
// Le travail se fait dans l'ISR ; la boucle principale reste libre.
// Exemple : Serial toutes les 2 bascules (0,5 Hz) si besoin.
}
Expected Verification
The LED blinks at 0.5 Hz (one toggle per second, meaning an off/on cycle every 2 seconds). Verify the accuracy by comparing 60 blinks against a watch: the error comes solely from the tolerance of the 16 MHz crystal. Suspend the loop with delay: the blinking continues, proving that the timer and an interrupt are driving the pin.
Common Errors
- Forgetting
noInterrupts/interruptsaround configuration: modifying TCCR1B/OCR1A while the timer is running can produce a spurious overflow.
- Not declaring the shared variable (
clignotements) asvolatile: without this keyword, the optimizer may remove its read inloop. - ISR too long: an ISR that prints or delays breaks other interrupts, including the Leonardo's USB (the USB service is itself interrupt-driven) — the connection may freeze.
- Wrong toggle register:
PINB = (1 << PINB7)toggles;PORTB ^= ...also works but performs a read-modify-write, which is less atomic in an interrupt context. - Incorrect OCR1A precalculation: with the 1024 prescaler, 1 Hz corresponds to OCR1A = 15624; at 2 Hz, 7811; the classic mistake is forgetting the +1 for counting from zero.
Other tutorials for this board
- Faire clignoter la LED intégrée (broche 13)
- Bouton et console série : Serial (USB) vs Serial1 (broches 0/1)
- Lire un capteur analogique : potentiomètre et ADC 10 bits
- Clavier USB : taper du texte avec la bibliothèque Keyboard
- Souris USB : déplacer le curseur avec la bibliothèque Mouse
- Asservir un servo moteur avec un potentiomètre (PWM)
Code examples for this board
clignotante.inoArduinobouton-led.inoArduinoclavier-auto-tape.inoArduinosouris-cercle.inoArduinotelecommande-media.inoArduinobouton-clic-souris.inoArduino