Guía técnica completa sobre el sistema de interrupciones y los módulos Timer del microcontrolador ATMEGA328P: vectores, modos de operación, registros de control y ejemplos prácticos en ensamblador.
El ATMEGA328P dispone de 31 vectores de interrupción, cada uno con una dirección de programa fija en la tabla de vectores. Cuando se produce un evento de interrupción, el procesador salta automáticamente a la dirección correspondiente para ejecutar la rutina de servicio (ISR). Los primeros 14 vectores cubren el reset del sistema, las interrupciones externas INT0–INT2, las interrupciones por cambio de pin PCINT0–PCINT3, el Watchdog Timer y las fuentes del Timer2 y Timer1.

Timers del ATMEGA328P
Los Timers son módulos hardware que operan en paralelo con el procesador, permitiendo que las operaciones de temporización y conteo se lleven a cabo de forma eficiente sin consumir ciclos de CPU. El procesador queda libre para ejecutar otras tareas mientras el timer trabaja de forma autónoma.
El ATMEGA328P incorpora tres timers independientes: Timer0 y Timer2 (ambos de 8 bits) y Timer1 (de 16 bits), lo que permite cubrir un amplio rango de frecuencias y resoluciones temporales según las necesidades de la aplicación.
Timer0
8 bits — uso general, PWM, CTC
Timer1
16 bits — alta resolución, captura
Timer2
8 bits — async, reloj RTC
Timer0 — Temporizador/Contador de 8 bits con PWM (Pág. 74)
El Timer0 es un módulo de propósito general de 8 bits capaz de generar señales PWM, temporizaciones precisas y eventos de comparación. Su versatilidad lo convierte en el timer más utilizado en aplicaciones embebidas básicas.
Dos unidades de comparación independientes
Pines PB3 (OC0A) y PB4 (OC0B) para salida de onda cuadrada o PWM.
Modo CTC (Clear Timer on Compare Match)
El contador se reinicia automáticamente al alcanzar el valor de OCR0A. Ideal para generar frecuencias precisas.
PWM de fase correcta y periodo variable
Modo de doble pendiente que genera señales PWM simétricas con menor distorsión de frecuencia.
Tres fuentes de interrupción permiten atender eventos sin polling.
El diagrama de bloques del Timer0 muestra la arquitectura interna del módulo: la lógica de control del reloj con el pre escalador, el registro contador TCNT0, las unidades comparadoras con OCR0A y OCR0B, y las salidas OC0A/OC0B, (PD5/PD6). Comprender esta arquitectura es clave para configurar correctamente el timer en cualquier modo de operación.

El Timer0 puede recibir su señal de reloj desde dos fuentes: el oscilador interno a través del prescaler, o una señal externa aplicada al pin T0. El prescaler divide la frecuencia del reloj del sistema (fclk) por factores de 1, 8, 64, 256 o 1024, permitiendo ajustar la resolución temporal del timer.

El registro TCNT0 es el corazón del Timer0. Al ser de 8 bits, puede almacenar valores entre 0x00 y 0xFF (0–255). El timer puede configurarse para contar hacia adelante (modo ascendente) o en ambas direcciones (modo fase correcta).
Cuando el Timer0 opera en modo ascendente y alcanza su valor máximo de 255, continúa contando desde 0 cíclicamente. Esta transición de 255 a 0 se denomina desbordamiento y activa el flag TOV0. También es posible limitar el conteo a un valor personalizado mediante el registro OCR0A.
El registro TCNT0 es de lectura y escritura, lo que permite precargar un valor inicial en el contador en cualquier momento. Esta característica es muy útil para calibrar temporizaciones con mayor precisión, especialmente cuando el período del timer no es un múltiplo exacto del tick de reloj.
El Timer0 incorpora dos unidades comparadoras que trabajan de forma continua, comparando en cada ciclo de reloj el valor actual de TCNT0 con los registros de comparación OCR0A y OCR0B.
Se activa el bit de bandera OCF0A. Puede generar una interrupción o modificar la salida OC0A. Base de los modos CTC y PWM en el canal A.
Se activa el bit de bandera OCF0B. Permite generar una segunda señal independiente en OC0B, útil para control de dos canales PWM simultáneos.
Esta comparación continua es la base para la generación de ondas cuadradas y señales PWM. El reloj del Timer/Contador 0 puede ser interno vía el prescaler o externo a través del pin T0.
El comportamiento del Timer0 se gobierna a través de tres grupos de bits de control ubicados en los registros TCCR0A y TCCR0B. Comprender la función de cada grupo es esencial para configurar correctamente el timer en cualquier aplicación.
Configuran la fuente de reloj y el factor del prescaler del Timer0. Permiten elegir entre reloj interno (dividido por 1, 8, 64, 256 o 1024) o reloj externo por el pin T0, en flanco de subida o bajada.
Waveform Generator Mode (WGM02:0)
Determinan el modo de operación del Timer0: Normal (conteo libre), CTC (reinicio por comparación) o los distintos modos PWM (rápido y fase correcta).
Compare Output Mode (COM0x1:0)
Deciden si las ondas generadas por los comparadores se emiten o no por los pines OC0A y OC0B del microcontrolador, y en qué modo (normal, toggle, clear, set).
Para entender los modos de operación del Timer0, es fundamental conocer los tres valores de referencia que definen los límites del ciclo de conteo. Estos valores aparecen constantemente en la documentación del datasheet y en las fórmulas de cálculo de frecuencia y período.
El contador alcanza el nivel más bajo cuando llega a 0x00. Es el punto de inicio en los modos ascendentes y el punto de retorno en los modos de doble pendiente.
El contador alcanza el valor más alto cuando llega a 0xFF (255 decimal). Es el tope absoluto del registro de 8 bits, independientemente del modo de operación.
El contador alcanza el valor tope cuando se iguala al mayor valor de la secuencia de conteo. Puede ser el valor fijo 0xFF o el valor almacenado en el registro OCR0A, según el modo seleccionado.
El Modo Normal (WGM02:0 = 0) es el modo de operación más simple del Timer0. El contador avanza siempre en dirección ascendente desde 0x00 hasta 0xFF sin ningún mecanismo de reinicio automático intermedio.
Al superar su valor máximo de 8 bits (TOP = 0xFF), el contador se reinicia automáticamente desde 0x00. En ese momento, la bandera de desbordamiento TOV0 se activa, pudiendo generar una interrupción si está habilitada.
Escritura directa en TCNT0
El registro TCNT0 es de lectura y escritura, por lo que es posible precargar un valor inicial en cualquier instante. Esto permite calibrar o ajustar las temporizaciones de forma precisa, compensando errores de temporización acumulativos.

El modo CTC (Clear Timer on Compare Match), seleccionado con WGM02:0 = 2, permite definir con precisión la frecuencia de las señales generadas. A diferencia del modo Normal, el contador no llega hasta 255, sino que se reinicia al alcanzar el valor cargado en el registro OCR0A.
El registro TCNT0 se incrementa desde BOTTOM hasta que TCNT0 = OCR0A. En ese instante, el contador se resetea a 0x00 y el ciclo comienza de nuevo.
La coincidencia activa el flag OCF0A, que puede usarse para disparar una interrupción o modificar la salida del pin OC0A mediante toggle.
El registro OCR0A es de lectura y escritura, lo que permite cambiar dinámicamente el tope del contador y ajustar la frecuencia de salida en tiempo de ejecución.
Los siguientes diagramas muestran la evolución del registro TCNT0 en el modo CTC y la señal resultante en el pin OC0A. El contador sube linealmente hasta alcanzar el valor de OCR0A, en cuyo momento se produce el reinicio y, si se ha configurado el modo toggle, la salida OC0A cambia de estado.


Para generar una forma de onda de salida en modo CTC, el pin OC0n (donde n puede ser A o B) puede invertir su nivel lógico cada vez que se produce una coincidencia de comparación. Esto se consigue configurando los bits de modo de comparación de salida a modo toggle (COM0x1:0 = 1).
El resultado es una señal cuadrada cuya frecuencia depende del valor de OCR0A, del pre escalador y del reloj del sistema. La frecuencia de la señal en OC0A se calcula como:

donde N es el factor del pre escalador. Esta fórmula es fundamental para calcular el valor correcto de OCR0A para una frecuencia de salida deseada.
El modo Fast PWM (WGM02:0 = 3) utiliza una rampa de pendiente única para generar señales PWM a la máxima frecuencia posible con un timer de 8 bits. El contador se incrementa desde BOTTOM (0x00) hasta MAX (0xFF) y luego se reinicia desde BOTTOM, generando una onda PWM con período fijo.
Al ser de pendiente única, el Fast PWM completa un ciclo completo en 256 ticks de reloj (dividido por el prescaler N), ofreciendo la mayor frecuencia de PWM posible en el Timer0.


En el modo Fast PWM, el Timer0 siempre cuenta de 0 a 255, lo que significa que el período (y por ende la frecuencia) de la señal PWM es constante. Esta es la principal limitación frente al modo de fase correcta. Sin embargo, modificando el valor del registro OCR0A es posible controlar el duty cycle de la onda PWM en tiempo real.


Los registros TCCR0A y TCCR0B (Timer/Counter Control Registers) son los registros de configuración principales del Timer0. En ellos se configuran los bits COM0x (modo de salida comparada), los bits WGM0x (modo de generación de onda) y los bits CS0x (selección de reloj/prescaler).

Cuando se configura el Timer0 en modo no-PWM y se desea sacar la señal por el pin OC0n, es necesario configurar dicho pin como salida en el registro de dirección de datos correspondiente (DDRx).

Además de los registros de control, el Timer0 utiliza otros registros para su operación: el registro de conteo TCNT0, los registros de comparación OCR0A y OCR0B, el registro de interrupciones TIMSK0 y el registro de flags TIFR0. La correcta configuración de todos ellos es indispensable para el funcionamiento del timer.


La tabla de Waveform Generation Mode (WGM) resume todos los modos de operación disponibles para el Timer0, junto con los valores de TOP, la fuente de actualización del registro OCRx y el comportamiento de los flags de interrupción. Esta tabla es la referencia esencial al configurar el timer.


El registro TCCR0B contiene los bits de selección de reloj (CS0x) y los bits de forzado de comparación de salida (FOC0n). El bit FOC0n es un bit de solo escritura que, cuando se activa, fuerza una comparación inmediata en el canal correspondiente sin esperar a que TCNT0 alcance OCR0n.


El registro TIMSK0 (Timer/Counter Interrupt Mask Register 0) habilita o deshabilita individualmente cada una de las tres fuentes de interrupción del Timer0: desbordamiento (TOIE0), comparación A (OCIE0A) y comparación B (OCIE0B). El registro TIFR0 contiene los flags de interrupción correspondientes.



Se desea generar una señal cuadrada de 2 kHz que salga por el pin OC0A (PB3) del ATMEGA164P, utilizando el Timer0 en modo CTC con toggle de salida. Con un reloj del sistema de 8 MHz y prescaler de 8, el valor de OCR0A se calcula:



Se desea generar una señal de 100 Hz que salga por el pin PB0, usando el Timer0 en modo CTC y atendiendo la interrupción por comparación para conmutar el pin manualmente. Al no usar el pin OC0A directamente, la salida se gestiona por software dentro de la ISR.





Este ejercicio muestra cómo utilizar la interrupción por desbordamiento (TOV0) del Timer0. Cuando el contador TCNT0 pasa de 0xFF a 0x00, se genera la interrupción que salta al vector $0x24 del mapa de vectores del ATMEGA164P, etiquetado como TIM0_OVF.

La segunda parte del ejercicio de overflow amplía el programa con la implementación de la sección de inicialización y la ISR completa. Se configura el Timer0 en modo Normal con el prescaler seleccionado, se habilita la interrupción de desbordamiento en TIMSK0 y se activan las interrupciones globales con la instrucción sei.

Timers — ATMEGA328P