Documente Academic
Documente Profesional
Documente Cultură
37
4 INTERRUPCIONES
Un microcontrolador puede poseer una gran variedad de mdulos dentro del mismo chip, por ejemplo: puertos de comunicaciones, convertidores ADC y DAC, comparadores, moduladores de ancho de pulso, etc. Estos mdulos comnmente trabajan independientemente del CPU del microcontrolador para reducir su carga de trabajo. Sin embargo llega el momento en que los mdulos necesitan comunicarse con el CPU, ya sea para transferencia de datos a memoria, procesamiento matemtico o transferencia de informacin de un mdulo a otro. La manera en que los mdulos se comunican con el CPU es interrumpindolo. De aqu el nombre de interrupciones. Cuando ocurre una interrupcin, el CPU deja pendiente lo que estaba haciendo para atender al mdulo que lo interrumpi; una vez atendido, el CPU regresa al punto donde fue interrumpido para continuar lo que estaba haciendo. En los PIC18 USB, la mayora de los mdulos y perifricos pueden generar interrupciones. Una interrupcin siempre va acompaada de una rutina de servicio de interrupcin, llamada, la cual llamaremos RSI (o ISR por sus siglas en ingles). Esta rutina, es la que indica lo que debe de hacer el microcontrolador al ser interrumpido, por lo tanto en la RSI escribimos el cdigo que queremos que el microcontrolador ejecute al ocurrir la interrupcin.
Interrupciones
38
Es a partir de esta localidad donde nosotros debemos escribir el cdigo que queremos que se ejecute cuando ocurre una interrupcin. Comnmente lo que se hace es poner una llamada a una funcin dentro del Vector de Interrupcin y dicha funcin est definida en otra parte del programa.
En el cdigo se muestra con azul el cdigo que nunca cambia, las palabras de color negro pueden variar al gusto del programador. Observe que dentro de la funcin VectorInterrupcion est un salto a la funcin denominada FuncionInterrupcion.
Una vez creado el Vector de Interrupcion ahora creamos la funcin a la que salta (FuncionInterrupcion) de la siguiente manera:
#pragma code #pragma interrupt FuncionInterrupcion void FuncionInterrupcion(void) { // Aqui ponemos nuestro cdigo // que queremos que se ejecute al ocurrir la interrupcin
// Antes de salir de la rutina de interrupcin debemos // limpiar la bandera de interrupcin que se activ }
La directiva #pragma interrupt indica al compilador que la funcin es una rutina de interrupcin.
Interrupciones
39
Hay que tener en cuenta que al Reset todas las fuentes de interrupcin se encuentran deshabilitadas.
Para habilitar alguna de estas interrupciones usando el lenguaje C18, se usan las siguientes funciones de la librera portb.h: OpenRB0INT OpenRB1INT OpenRB2INT Las cuales se muestran en la Figura 4-1.
Interrupciones
40
Interrupciones
41
/* Interrupcin INT1 * * Contador en PORTA * Cada vez que recibe un flanco descendente en INT1 reinicia contador */ #include <p18cxxx.h> #include <portb.h> #include <delays.h> // Prototipo de funcion void FuncionInterrupcion(void); // Seccin de variables globales no inicializadas #pragma udata unsigned char contador; //Cdigo para bootloader extern void _startup (void); #pragma code REMAPPED_RESET_VECTOR = 0x1000 void _reset (void) { _asm goto _startup _endasm } // Seccin de cdigo #pragma code // Aqu inicia el programa void main() { TRISA = 0; // PORTA como salida TRISB = 0xFF; // Configura todo PORTB como entrada
ADCON1 |= 0x0f; // Configura pines como digitales // Configura interrupcin externa del pin RB1 OpenRB1INT(PORTB_CHANGE_INT_ON & FALLING_EDGE_INT & PORTB_PULLUPS_ON); // Habilitacin global de interrupciones INTCONbits.GIE = 1; // Inicia contador de pulsos contador = 0;
Interrupciones
while(1) { LATA = contador; contador ++; Delay10KTCYx(10); //retardo de 10,000 TCYs } } // Vector de Interrupcin (direccin 0x1008 si usamos bootloader) #pragma code Interrupcion = 0x1008 // Si no se usa bootloader es 0x8 void VectorInterrupcion(void) { _asm GOTO FuncionInterrupcion _endasm } /****** Rutina de Interrupcin INT1 *****/ #pragma interrupt FuncionInterrupcion void FuncionInterrupcion(void) { /* Reinicia el contador */ contador = 0; // Limpia la bandera de interrupcin INTCON3bits.INT1IF = 0; } Programa 4-1. INT1 modo compatibilidad
42
Interrupciones
43
#include <p18cxxx.h> #include <portb.h> #include <delays.h> // Prototipo de funcion void FuncionInterrupcion(void); // Seccin de variables globales no inicializadas #pragma udata char contador; char cuenta; //Cdigo para bootloader extern void _startup (void); #pragma code REMAPPED_RESET_VECTOR = 0x1000 void _reset (void) { _asm goto _startup _endasm } // Seccin de cdigo #pragma code // Aqu inicia el programa void main() { TRISA = 0; // PORTA como salida TRISB = 0xFF; // Configura todo PORTB como entrada
ADCON1 |= 0x0f; // Configura pines como digitales // Configura interrupcin externa del pin RB1
Interrupciones
OpenRB1INT(PORTB_CHANGE_INT_ON & FALLING_EDGE_INT & PORTB_PULLUPS_ON); // Configura interrupcin externa del pin RB2 OpenRB2INT(PORTB_CHANGE_INT_ON & FALLING_EDGE_INT & PORTB_PULLUPS_ON); // Habilitacin global de interrupciones INTCONbits.GIE = 1; // Inicia contador de pulsos contador = 0; cuenta = 1; while(1) { LATA = contador; if(cuenta) contador ++; Delay10KTCYx(30); } } // Vector de Interrupcin (direccin 0x1008 si usamos bootloader) #pragma code Interrupcion = 0x1008 // Si no se usa bootloader es 0x8 void VectorInterrupcion(void) { _asm GOTO FuncionInterrupcion _endasm } // Seccin de cdigo #pragma code #pragma interrupt FuncionInterrupcion void FuncionInterrupcion(void) { // Si se dispar INT1 if(INTCON3bits.INT1IF) { contador = 0; // reinicia contador INTCON3bits.INT1IF = 0; } // Si se dispar INT2 else if(INTCON3bits.INT2IF) { cuenta = 1-cuenta; // pausa o reanuda contador INTCON3bits.INT2IF = 0; } } Programa 4-2. INT1 e INT2 modo compatibilidad
44