AVR programación en C – 06 Interrupciones en los AVR

Imagen: protostack  

Las interrupciones son eventos especiales que se generan interna o externamente en el microcontrolador que pausa momentáneamente  la ejecución del programa para realizar una tarea breve, y después volver al punto donde se quedó ejecutando el programa. Esto sirve para que el microcontrolador no este siempre trabajando, por ejemplo, en checar el estado de una entrada constantemente, y solo poner atención cuando el evento deseado ocurre.

En esta entrada se tratará de explicar como funciona el sistema de interrupciones de los AVR’s, los vectores y registros que lo componen tanto como su programación en C con el compilador avr-gcc y avr-libc.

Imaginen que están en la mesa de su casa tomando el desayuno, de repente el teléfono suena, te levantas, atiendes la llamada, cuelgas y vuelves a la mesa a desayunar, esa sería una analogía de lo que es una interrupción.

Lo mismo pasa con los microcontroladores y microprocesadores, tienen una método de que otros dispositivos externos (o internos) al micro, puedan mandarle una alerta sobre algo, y este atienda la alerta y continúe su camino.

Los microcontroladores AVR tienen un carecen de interrupciones por software, lo que es útil para tareas especiales de sistemas operativos, como intercambio de procesos, o manejo de excepciones, aquí nos concentraremos solamente en las interrupciones por Hardware.

Las interrupciones se organizan en vectores de interrupción con prioridad. Cada modelo de AVR tiene un conjunto diferente de fuentes de interrupción, podemos averiguar cuales son las fuentes que pueden interrumpir al microcontrolador viendo su datasheet. Los vectores de interrupción no son mas que direcciones especificas de la memoria de programa en la que se encuentra una instrucción de salto al fragmento de código que se debe ejecutar acorde a la fuente que lo interrumpe.

En este post se hablará de las interrupciones del ATmega16, pero es muy fácil escribir código para otro microcontrolador, basta echar un vistazo a su datasheet para conocer los vectores y fuentes de interrupción.

Tabla de vectores de interrupciones del ATmega16

vectores atmega16

 

Como se puede observar en la tabla, los vectores de interrupción se colocan en las primeras direcciones de la memoria de programa.

 

Manejo de Interrupciones

Para manejar una interrupción hay que seguir una serie de pasos para habilitarla, dependiendo de cual sea, se programan los registros asociados a la fuente de interrupción:

  1. Habilitar la interrupción deseada en el registro correspondiente.
  2. Agregar la función que contenga el código de interrupción.
  3. Habilitar las interrupciones globales.

En el compilador AVR-GCC, la tabla de vectores está predefinido para que apunte a rutinas de interrupción con los nombres predeterminados. Mediante el uso de un nombre apropiado, su rutina será llamada cuando se produce la interrupción correspondiente.

Para programar una una función en C que maneje una interrupción, es necesario hacer la inclusión de la librería <avr/interrupt.h>, que contiene las macros necesarias para definir funciones, habilitar y deshabilitar las interrupciones globales.. Las macros con los nombres de los vectores de interrupción se encuentra en la librería <avr/io.h> para cada modelo de micro.

La macro ISR( __VECTOR__ ) sirve para declarar la función de servicio de interrupción, y recibe como parámetro el vector de interrupción que se atenderá. Las macros sei() y cli() habilitan y deshabilitan respectivamente, las interrupciones modificando el bit I (bit 7) del registro SREG.

#include <avr/interrupt.h>

ISR(ADC_vect)
{
    // codigo de usuario
}
    sei();    // habilta las interrupciones
    cli();    // deshabilita las interrupciones.

Aquí dejo un ejemplo para el ATmega16 de como programar e implementar las interrupciones, para este caso se habilita la interrupción del ADC, que se dispara cuando una conversión termina y muestra el resultado (de 10 bits) en los puertos B y C:

//////////////////////////////////////////////////////////////////////////////

#include <avr/io.h>
#include <avr/interrupt.h>

void ADC_Init() {

	ADMUX = _BV(REFS0);
	ADCSRA = _BV(ADEN) |  _BV(ADIE);

}

ISR(ADC_vect) {

	unsigned char adc_value = ADC;

	PORTB = adc_value;
	PORTC = adc_value >> 8;

	ADCSRA |= _BV(ADSC);
}

void Init_System() {

	DDRA = 0x00;
	DDRB = DDRC = 0xFF;
	PORTB = PORTC = 0;
ADC_Init();
	sei();
}

int main(void) {

	Init_System();

	ADCSRA |= _BV(ADSC);

	while(1){}

	return 0;
}

//////////////////////////////////////////////////////////////////////////////

La función ADC_Init() habilita el ADC con un preescaler de 128 y la referencia AVCC, junto con la interrupción de conversión. La función que se ejecuta al activarse la interrupción se declara con la macro ISR(ADC_vect) , y lo que hace es leer el resultado de la conversión analógica, lo muestra por los puertos B y C, e inicia nuevamente una conversión. El parámetro de la macro es el vector de la interrupción del ADC, para este caso, pero puede ser cualquier otro de los nombrados en la tabla de vectores de interrupción del datasheet pero con la terminación _vectLa función Init_System() programa el puerto A como entrada, los puertos B y C como salida y los inicializa con 0, llama a la función ADC_Init() y habilita las interrupciones globales. La función main() llama a la función Init_System() y realiza la primera conversión del ADC y entra en un ciclo infinito, ejecutando solo así el código de la interrupción.

Como ven es muy fácil programar las funciones para atender interrupciones con el compilador AVR-GCC, existen otras propiedades interesantes de las interrupciones, como hacer que 2 interrupciones ejecuten una misma función.

Les dejo el link del manual de usuario de la avr-libc donde viene toda esta información:

Interrucpciones AVR

 

En la próxima entrada veremos como programar la USART del ATmega16, un modulo muy útil para la depuración de programas y la creación de interfaces con la computadora.

 

Fred!

2 comentarios sobre “AVR programación en C – 06 Interrupciones en los AVR

Add yours

Dejar un comentario

Crea una web o blog en WordPress.com

Subir ↑