jueves, 30 de mayo de 2019

Práctica 5.b Interrupciones internas (Internal interrupts pic32)


Práctica 5.b Interrupciones internas



Las interrupciones internas son generadas por módulos contenidos en la pastilla del microcontrolador, estos módulos pueden ser el UART, los temporizadores(Timer), el PWM, etc. En esta práctica se verá el uso de la interrupción generada por “Timer 1”.



En la práctica 3 se usó el “Timer 1” para generar un retardo. Como se recordará el “Timer” se puede ver como un contador. El conteo lo inicia en 0 y guarda en el registro TMRx la cuenta que lleva. El número hasta el que va a contar(periodo) lo pone el usuario en el registro PRx, y cuando TMRx es igual a PRx se levanta una bandera y/o se genera una interrupción. En la práctica 3, el CPU estuvo vigilando la bandera, sin realizar otro trabajo. Esta manera de usar el “Timer” tiene varias deficiencias, la más importante es que el CPU está dedicado a vigilar el estado de la bandera, otra deficiencia es que se complica obtener periodos precisos, ya que cada vez que se inicia un periodo se lleva a cabo un cambio de contexto en el caso de que la configuración y arranque del “Timer” se encuentren en una función, además de los Tcy’s necesarios para hacer las configuraciones y comparaciones al vigilar el estado de la bandera del “Timer”.





Pasos para configurar la interrupción del “Timer 1”



  1. Elegir modo, ya sea mono ó multi-vector, si es multi-vector se pone a uno el bit MVEC(12) del registro INTCON
  2. Se establecen las propiedades de la interrupción. En la figura 5.1, se puede ver que la interrupción generada por el “Timer 1” Tiene el vector 4, su bandera se encuentra en el bit 4 de IFS0, el bit de habilitación se encuentra en el bit 4 de IEC0 y su prioridad se fija en los bits 4, 3 y 2 del registro IPC1 y la sub-prioridad en los bits 1 y 0 del mismo registro IPC1.
  3. Se define la función que se ejecutará cuando se active la interrupción (DS51686E-p133). Esta función ya se encuentra predefinida y esta definición es la misma para todas las interrupciones, tanto internas como externas. En esta práctica queda definida de la siguiente manera:                 void __ISR(4, IPL7AUTO) invierte_led(void)

Se usa el mismo equipo y material de la práctica 5a

El circuito usado es el del sistema mínimo, no se requiere el circuito que se agrega en la figura 5.1, y por lo tanto tampoco se requieren esos componentes(“push-button” y la resistencia de 1k)

El programa

/*

* x32_05b.c

* Autor: Jesus Acosta

* 12 Abril 2019

* Ejemplo de interrupci'on timer 1

* Usa oscilador FRCPLL

* Micro = PIC32MX220F032B

* No requiere el uso de plib.h

*/



#include <p32xxxx.h>

#include <sys/attribs.h>          //Para las macros de Interrupciones



#pragma config ICESEL = ICS_PGx2 //PGEC = pin 22

                                                                  //PGED = pin 21



#pragma config JTAGEN = OFF      // Deshabilita JTAG

#pragma config FSOSCEN = OFF     // Deshabilita oscilador secundario

#pragma config FWDTEN = OFF      // Deshabilita watchdog timer



#pragma config FNOSC=FRCPLL      // Usa oscilador FRC con PLL [8MHz]]

//#pragma config FPLLIDIV=DIV_4  // Pero como PLL FPLLIDIV no lo divide

                                                                  // Entonces entran 4MHZ

#pragma config FPLLMUL=MUL_16    // Multiplica por 16 [Ahora 64MHz]

#pragma config FPLLODIV=DIV_8    // Divide entre 8 [Ahora 8MHz]

#pragma config FPBDIV = DIV_1    // Divide entre 1 el reloj a los

                                                                  // periféricos

#pragma config DEBUG = OFF       // Se pone a ON/OFF para depuraci'on

                                                                  // usando ICD3



void retardo1ms(void );                     //Prototipo función

void __ISR(4, IPL7AUTO) invierte_led(void); //Prototipo funci'on

int main(void);                             //Prototipo funcion main


//************** Programa principal **********************

int main(void){

    TRISACLR = 0x0010; //Se pone a cero bit 4 de TRISA (Output)

    LATASET = 0x0010; //Se pone a uno bit LATA4



    //Configura la interrupci'on del timer 1

    __builtin_disable_interrupts(); //Deshabilita todas las interrupciones

    IEC0bits.T1IE = 0; // Inhabilita interrupci'on timer 1

    INTCONbits.MVEC = 1; // Multivector habilitado

    IPC1bits.T1IP = 7; // Prioridad, 7 la mas alta

    IPC1bits.T1IS = 3; // Sub-prioridad 3, la mas alta

    IFS0bits.T1IF = 0; // Se baja bandera

    IEC0bits.T1IE = 1; // Habilita interrupci'on T1

    __builtin_enable_interrupts(); //Habilita todas las interrupciones



    retardo1ms(); //Se configura y arranca el “timer 1” solo una vez


    //Ciclo infinito haciendo nada

    while(1){

       asm("nop"); //Hace nada

    }

}



void retardo1ms(void ){

    /* Se asegura el reset del timer 1 */

    T1CON = 0;

    TMR1 = 0;

    PR1 = 7999; //Se pone el periodo

    IFS0bits.T1IF = 0; //Baja bandera

    IEC0bits.T1IE = 1; //Habilita interrupci'on del timer 1

    T1CON = 0x8000;    //Configura T1CON=1000 0000 0000 0000

                                          //con prescaler 1:1

    return;

}



//Funci'on que se ejecuta con la interupci'on de T1

void __ISR(4, IPL7AUTO) invierte_led(void){

    LATAINV = 0x0010; //Invierte estado bit LATA4

    IFS0bits.T1IF = 0; //Baja bandera

}





Descripción del programa:

Esta práctica consiste en un programa donde el CPU por única vez configura y arranca al “Timer 1”, después se queda ejecutando un ciclo infinito en cuyo interior solo se encuentra la instrucción “nop” que es un periodo Tcy inactivo del CPU. Cuando PR1 y TMR1 son iguales el “Timer 1” genera una interrupción y reinicia la cuenta poniendo a cero TMR1. La interrupción fuerza a que el CPU abandone el ciclo infinito que estaba ejecutando y realice las acciones que están programadas en la función asociada al “Timer 1”, esta función cambia el estado del puerto RA4. Si tenía un uno, cambia a cero, y si tenía un cero cambia a uno. Después el CPU regresa a continuar ejecutando el ciclo infinito.





Bibliografía:

Capítulo 7 del manual de referencia del pic32 (DS60001168K)

Capítulo 12 del manual de referencia del pic32 (DS60001168K)





Proyecto:



Realizar un contador de revoluciones por minuto (RPM) y desplegar el resultado en un LCD.

No hay comentarios.:

Publicar un comentario