🛠 Registres AVR et interruption timer
Objetivos
Salir de la abstracción de Arduino programando directamente los registros del ATmega328P: configurar el timer1 en modo CTC (Clear Timer on Compare Match) para generar una interrupción periódica precisa, sin depender de delay ni de millis. La ISR solo conmuta el LED integrado — la disciplina clásica de "ISR corta" en AVR.
Material
- 1 × Arduino Nano clásico (ATmega328P @ 16 MHz, cristal cerámico)
- El LED integrado (pin 13); un osciloscopio o un analizador lógico es una ventaja para medir el periodo
- Ninguna conexión externa obligatoria
Código completo
// Timer1 en CTC : interruption ~1 Hz, ISR bascule la LED 13
// 16 MHz / (1024 * 15625) = 1 Hz environ
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_COMPA_vect) { // appelee a chaque compare match
PINB |= _BV(PB5); // bascule directe de la broche 13 (PB5)
}
void setup {
DDRB |= _BV(DDB5); // PB5 (broche 13) en sortie
noInterrupts;
TCCR1A = 0; // mode normal d'abord
TCCR1B = _BV(WGM12); // CTC sur OCR1A
TCNT1 = 0;
OCR1A = 15624; // 16e6/1024/15625 = 1 Hz
TCCR1B |= _BV(CS12) | _BV(CS10); // prescaler 1024 : demarre
TIMSK1 |= _BV(OCIE1A); // autorise l'IT compare match A
interrupts;
}
void loop {
// Le coeur tourne sans delay : tout est dans l'ISR
}
Verificación esperada
El LED integrado conmuta exactamente una vez por segundo, con una regularidad de cristal (el cristal de 16 MHz es mucho más estable que las derivas de un delay anidado). El código ocupa unos cientos de bytes de flash. Al cortar la autorización de interrupciones (cli), el LED se congela inmediatamente — prueba de que solo el timer trabaja.
Errores frecuentes
- ISR demasiado larga: llamar a Serial.print o delay dentro de una ISR bloquea las otras interrupciones y corrompe millis; la ISR debe permanecer mínima.
- Olvidar el bit WGM12 (modo CTC) o CS12|CS10 (prescaler): el timer nunca arranca, no se observa ninguna conmutación.
- Modificar una variable compartida ISR/loop sin volatile ni sección crítica: el compilador optimiza la lectura y loop nunca ve el cambio.
- Confundir PB5 y el pin 13: la correspondencia física es propia del bootloader de Arduino en el 328P; verificar la hoja de pines del encapsulado TQFP/MLF.
- >
Otros tutoriales para esta placa
Ejemplos de código para esta placa
buzzer-melodie.inoArduinoservo-sweep.inoArduinoultrason-hcsr04.inoArduinolcd-i2c.inoArduinoeeprom-contre.inoArduinosommeil-watchdog.inoArduino