Con el hilo de al lado sobre TMR0 en el 16F84A, un tema relacionado que da para bastante: interrupciones frente a polling (sondeo activo) en microcontroladores, ¿cuándo compensa cada uno?
Polling: el programa comprueba activamente y en bucle si ha pasado algo («¿ya desbordó el timer?», «¿hay un bit nuevo en el UART?»), sin hacer nada útil mientras tanto. Es la forma más simple de programar y de depurar (el flujo del programa es lineal, fácil de seguir con un simulador paso a paso), pero el microcontrolador no puede hacer nada más mientras espera.
Interrupciones: el hardware avisa automáticamente al programa cuando pasa algo relevante, interrumpiendo lo que estuviera haciendo para ejecutar una rutina específica, y luego vuelve exactamente a donde estaba. Esto permite que el microcontrolador siga haciendo trabajo útil (leer sensores, actualizar una pantalla, procesar otra tarea) mientras espera en segundo plano a que ocurra el evento.
Cuándo usar cada uno, en la práctica:
Polling tiene sentido cuando el microcontrolador no tiene nada más que hacer mientras espera (un programa muy simple, tipo «enciende y apaga un LED»), o cuando necesitas una respuesta con latencia mínima garantizada y predecible, sin el overhead (pequeño pero real) de entrar y salir de una rutina de interrupción.
Interrupciones compensan claramente en cuanto el programa tiene que hacer varias cosas «a la vez» (leer un botón, gestionar comunicación serie, y mantener un temporizador, todo simultáneamente), o cuando el evento que esperas puede ocurrir en cualquier momento de forma impredecible (una pulsación de botón del usuario, un byte llegando por UART) y no quieres estar constantemente comprobando «¿ya, ya, ya?» desperdiciando ciclos de reloj en el sondeo.
Un matiz que se aprende con la práctica: las rutinas de interrupción deben ser lo más cortas posible (guardar un dato, poner una bandera, y salir), la lógica pesada se hace después en el bucle principal comprobando esa bandera. Meter mucho código dentro de la propia interrupción es una fuente clásica de bugs difíciles de depurar (interrupciones anidadas, tiempos de respuesta impredecibles).
Nuria
La regla que a mí me funciona bien: interrupciones para eventos poco frecuentes e impredecibles donde importa reaccionar rápido, polling para todo lo que pasa a un ritmo alto y predecible donde el propio bucle principal ya está pendiente de todos modos.
Ejemplos claros de cuándo usar interrupciones: pulsación de un botón físico (no sabes cuándo va a pasar, y no quieres tener el micro comprobando el pin en bucle constantemente desperdiciando ciclos), llegada de un byte por UART/comunicación serie (si no lo procesas rápido puede perderse el siguiente byte), o cualquier evento de "esto ha pasado, atiéndelo ya" donde el tiempo entre eventos es mucho mayor que el tiempo de ejecución del propio microcontrolador.
Ejemplos claros de cuándo usar polling: lecturas de un sensor a una frecuencia fija que ya controlas tú desde el bucle principal (no tiene sentido montar una interrupción por temporizador si de todas formas vas a comprobar el valor en cada iteración del loop principal), o situaciones donde necesitas timing muy determinista y la latencia variable de entrar/salir de una rutina de interrupción (el "jitter" de interrupción) te complica más de lo que te ayuda.
El error típico de quien empieza es abusar de interrupciones para todo "por si acaso", sin darse cuenta de que cada interrupción añade complejidad real (condiciones de carrera con el código principal, necesidad de variables volatile, cuidado con qué se puede hacer dentro de una ISR sin bloquear el sistema). Si el bucle principal ya puede comprobar algo a tiempo sin problema, muchas veces polling simple es más fácil de razonar y depurar.
Marta