Autor Tema: Problema con múltiples interrupciones en PIC 32  (Leído 7861 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado lean_ing

  • PIC10
  • *
  • Mensajes: 6
Problema con múltiples interrupciones en PIC 32
« en: 12 de Enero de 2013, 15:39:11 »
Hola a todos. Les cuento que estoy empezando a utilizar PIC 32, este micro en particular PIC32MX230f064B. Hice un programa extremadamente sencillo para hacer sonar un Buzzer. Tengo dos interrupciones, la del Timer 3 (tengo configurado los timer 2 y 3 juntos, como uno solo de 32 bits) y la del conversor ADC. El problema es que al asignar las prioridades, entra una interrupción o la otra, nunca las dos. Sin embargo, al verificar los registros IFS, veo que el flag de ambas interrupciones están en "1", pero solo entra la interrupción de mayor prioridad. ¿Acaso no debería entrar la interrupción de menor prioridad una vez que la de mayor prioridad termino, ya que el flag está en 1?.

Por cierto, al usar las interrupciones individualmente se ejecutan sin problema. El inconveniente es definitivamente cuando utilizo varias interrupciones a la vez.

A continuación adjunto mi codigo:
Citar
#include <proc/p32mx230f064b.h>

// DEVCFG3
// USERID = No Setting
#pragma config PMDL1WAY = ON            // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON             // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = OFF           // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF          // USB VBUS ON Selection (Controlled by Port Function)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // PLL Input Divider (1x Divider)
#pragma config FPLLMUL = MUL_15         // PLL Multiplier (15x Multiplier)
#pragma config UPLLIDIV = DIV_1         // USB PLL Input Divider (1x Divider)
#pragma config UPLLEN = OFF             // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)

// DEVCFG1
#pragma config FNOSC = PRI              // Oscillator Selection Bits (Primary Osc (XT,HS,EC))
#pragma config FSOSCEN = ON             // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WISZ_25      // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = ON              // JTAG Enable (JTAG Port Enabled)
#pragma config ICESEL = ICS_PGx3        // ICE/ICD Comm Channel Select (Communicate on PGEC3/PGED3)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)




#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <sys/attribs.h>
#include <plib.h>


int main() {
 
    INTEnableSystemMultiVectoredInt();
    //INTEnableSystemSingleVectoredInt();

    ANSELB=0x8000;  //RB15 como analogico y los demas como digitales
    TRISB=0x8000;   //1=entrada; 0=salida
    LATB=1;         //Reseteo los puertos

    //Configuración ADC************************************************
    AD1CHSbits.CH0SA=9;         //Entrada de muestras por AN9
    AD1CON1=0x00e4;
    AD1CON2=0x0000;
    AD1CON3=0x0103;
    IEC0bits.AD1IE=1;
    IPC5bits.AD1IP=7;           //Prioridad
    //IPC5bits.AD1IS=1;           //Sub-prioridad
    IFS0bits.AD1IF=0;
    AD1CON1bits.ADON=1;
    //******************************************************************/


    //Configuración Timer 2 y 3 como 32 bits*********************************
    T2CONbits.ON=0;
    T2CONbits.TCKPS=0;      //Prescaler 1:1
    T3CONbits.ON=0;
    T2CONbits.T32=1;        //Timers 2 y 3 como contadores de 32 bits
    TMR2=0;                 //Borro contenido de los registros del timer
    PR2=0x00002710;         //Cargo registros de comparación del timer (valor en el cual se resetea)
    IPC3SET = 0x00000004;   // Set priority level = 1
    IPC3SET = 0x00000001;   // Set sub-priority level = 1
                            // Could have also done this in single operation
                            // by assigning IPC5SET = 0x00000005
    IFS0bits.T3IF=0;        //Borro flag de interrupción
    IPC3bits.T3IP=6;        //Prioridad
    //IPC3bits.T3IS=3;        //Sub-prioridad
    IEC0bits.T3IE=1;        //Enable Timer5 interrupts
    T2CONbits.ON=1;         //Enciendo el timer
   
    //*******************************************************************
   

   

    while(1)
     {
 
     }
}

void __ISR(_ADC_VECTOR/*,IPL6AUTO*/) ADCHandler(void)
{
    IFS0bits.AD1IF=0;       //Borro flag de interrupción
    T2CONbits.ON=0;
    TMR2=0;
    PR2=ADC1BUF0;
    T2CONbits.ON=1;
}



void __ISR(_TIMER_3_VECTOR/*, IPL7AUTO*/) Timer3Handler(void)
{
        IFS0bits.T3IF=0;
        LATBbits.LATB14=!LATBbits.LATB14;
       
}

Como datos adicionales que pueden servir, estoy usando MPLAB X 1.60 y el PICKIT 3.
Cada esfuerzo por clarificar lo que es ciencia y de generar entusiasmo popular sobre ella es un beneficio para nuestra civilización global. Del mismo modo, demostrar la superficialidad de la superstición, la pseudociencia, el pensamiento new age y el fundamentalismo religioso es un servicio a la civilización.

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #1 en: 12 de Enero de 2013, 19:44:37 »
Todavía no he tenido la necesidad de trabajar con mas de una interrupción, pero por ahí te doy una idea.

Quizás puedes trabajar con un solo vector de interrupciones y en la rutina de atención a las interrupciones defines tu el orden de tratamiento.

El borrado de los flag es conveniente hacerlo antes de salir de la rutina de atención a la interrupción.

EDITO:
La prioridad de las interrupciones trabaja algo así:
Tu programa se ejecuta normalmente, se presenta una interrupcion de alta prioridad, el micro se dirige a la rutina de atencion de las interrupciones de alta prioridad y si mientras ejecutas el codigo de atencion a interrupcion surge otra interrupcion la vas a perder, salvo que antes de salir chequees que se ha activado el flag. se activará el flag correspondiente, cuando sale de la rutina de alta prioridad se dirige a la rutina de baja prioridad.

Si se interrumpe el programa con una de baja prioridad y mientras atiendes esa interrupcion surge una de alta prioridad, hay si se va de la rutina a atender la alta prioridad y luego retorna a la rutina de baja prioridad.

Quizas alguien que ya haya trabajado con prioridades te puede dar una idea mas clara  :oops:
« Última modificación: 13 de Enero de 2013, 09:59:45 por willynovi »
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #2 en: 12 de Enero de 2013, 20:11:46 »
Hola! Raro que no funcione, mirando rápidamente no veo algo raro... Yo implemento de la siguiente manera: configuro el modulo, luego habilito su interrupción, establezco su nivel de prioridad y su sub-nivel de prioridad solo si hay otros con la misma prioridad. Finalizado la configuración de todos los módulos  determino el tipo de interrupción a utilizar y realizo la habilitación general. Por ejemplo:



Código: C
  1. RtccInit();
  2.     while(RtccGetClkStat()!=RTCC_CLK_ON);
  3.  
  4.     RtccChimeEnable();
  5.     RtccSetAlarmRptCount(0);
  6.     RtccSetAlarmRpt(RTCC_RPT_SEC);                      // Cada 1 seg.
  7.     RtccAlarmEnable();
  8.     INTSetVectorPriority(INT_RTCC_VECTOR, INT_PRIORITY_LEVEL_3);
  9.     INTEnable(INT_RTCC, INT_ENABLED);
  10.  
  11.     OpenTimer3(T3_ON | T3_IDLE_STOP | T3_GATE_OFF | T3_PS_1_2 | T3_SOURCE_INT, 40000);
  12.     ConfigIntTimer3(T3_INT_ON | T3_INT_PRIOR_2);
  13.  
  14.     INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
  15.     INTEnableInterrupts();

De esa manera funciona y he tenido varias fuentes de interrupción.


Saludos!
« Última modificación: 12 de Enero de 2013, 20:14:40 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #3 en: 12 de Enero de 2013, 20:14:22 »
La prioridad de las interrupciones trabaja algo así:
Tu programa se ejecuta normalmente, se presenta una interrupcion de alta prioridad, el micro se dirige a la rutina de atencion de las interrupciones de alta prioridad y si mientras ejecutas el codigo de atencion a interrupcion surge otra interrupcion la vas a perder, salvo que antes de salir chequees que se ha activado el flag.

Eso no ocurre, se atiende igualmente la de baja prioridad, pero solo después de terminar con la de mayor prioridad.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #4 en: 12 de Enero de 2013, 20:21:00 »
La prioridad de las interrupciones trabaja algo así:
Tu programa se ejecuta normalmente, se presenta una interrupcion de alta prioridad, el micro se dirige a la rutina de atencion de las interrupciones de alta prioridad y si mientras ejecutas el codigo de atencion a interrupcion surge otra interrupcion la vas a perder, salvo que antes de salir chequees que se ha activado el flag.

Eso no ocurre, se atiende igualmente la de baja prioridad, pero solo después de terminar con la de mayor prioridad.


Saludos!

Luego de escribirlo me quedé con la duda, es así en los PIC32 o te refieres a todos los que tengan posibilidad de definir prioridades?

Tambien de curiosidad me leí por arriba el "PIC32 Family Reference Manual" y creo que es lectura obligatoria para quien se inicie en estos bichos  ;-)
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #5 en: 12 de Enero de 2013, 20:24:36 »
En cualquiera, porque el flag queda activo, así que al salir de la interrupción el controlador lo detecta y re-direcciona al vector adecuado. Sea multi-vector o simple.
Salvo que se implemente mal y se borre un flag que no corresponda.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #6 en: 13 de Enero de 2013, 08:53:15 »
Recordé un tema que hay que tener atención y por lo que veo lo tienes comentado, ojo en ello! Cuando usas múltiples vectores, en la interrupción debe estar correctamente indicado:

void __ISR(_RTCC_VECTOR, ipl3) RtccIsr(void){....

void __ISR(_TIMER_3_VECTOR, ipl2) Timer3Handler(void){...


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado lean_ing

  • PIC10
  • *
  • Mensajes: 6
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #7 en: 13 de Enero de 2013, 13:53:44 »
Muchas gracias Suky y willynovi por responder.

 
Recordé un tema que hay que tener atención y por lo que veo lo tienes comentado, ojo en ello! Cuando usas múltiples vectores, en la interrupción debe estar correctamente indicado:

void __ISR(_RTCC_VECTOR, ipl3) RtccIsr(void){....

void __ISR(_TIMER_3_VECTOR, ipl2) Timer3Handler(void){...

Respecto a esto Suky, tengo entendido que iplx (x es un numero del 1 al 7) define la prioridad de interrupción, pero si la tengo configurada mas arriba con la instrucción IPC3bits.T3IP=7 por ejemplo, esto es redundante, ¿O me equivoco?

Les cuento ahora que ya me funciona un poco mejor el código, entra a las dos interrupciones gracias a que seguí la recomendación de Suky de habilitar los vectores luego de toda la configuración, y agregue ademas la instrucción INTEnableInterrupts(). Pero en la rutina de atención a la interrupción del adc no puedo modificar el contenido del PR2 igualándolo al valor digitalizado, ya que si hago esto ingresa a la interrupción del Timer cuando al programa se le antoje, es decir a veces entra y a veces no...es muy raro, no logro entender porque...

El código ahora me quedo así, y funciona muy bien las dos interrupciones, que era el problema principal  :) :
Código: [Seleccionar]
#include <proc/p32mx230f064b.h>

// DEVCFG3
// USERID = No Setting
#pragma config PMDL1WAY = ON            // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON             // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = OFF           // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF          // USB VBUS ON Selection (Controlled by Port Function)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // PLL Input Divider (1x Divider)
#pragma config FPLLMUL = MUL_15         // PLL Multiplier (15x Multiplier)
#pragma config UPLLIDIV = DIV_1         // USB PLL Input Divider (1x Divider)
#pragma config UPLLEN = OFF             // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)

// DEVCFG1
#pragma config FNOSC = PRI              // Oscillator Selection Bits (Primary Osc (XT,HS,EC))
#pragma config FSOSCEN = ON             // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WISZ_25      // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = ON              // JTAG Enable (JTAG Port Enabled)
#pragma config ICESEL = ICS_PGx3        // ICE/ICD Comm Channel Select (Communicate on PGEC3/PGED3)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)




#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <sys/attribs.h>
#include <plib.h>


int main() {
 


    ANSELB=0x8000;  //RB15 como analogico y los demas como digitales
    TRISB=0x8000;   //1=entrada; 0=salida
    LATB=1;         //Reseteo los puertos

    //Configuración ADC************************************************
    AD1CHSbits.CH0SA=9;         //Entrada de muestras por AN9
    AD1CON1=0x00e4;
    AD1CON2=0x0000;
    AD1CON3=0x0103;
    IEC0bits.AD1IE=1;
    IPC5bits.AD1IP=6;           //Prioridad
    //IPC5bits.AD1IS=1;           //Sub-prioridad
    IFS0bits.AD1IF=0;
    AD1CON1bits.ADON=1;
    //******************************************************************/


    //Configuración Timer 2 y 3 como 32 bits*********************************
    T2CONbits.ON=0;
    T2CONbits.TCKPS=0;      //Prescaler 1:1
    T3CONbits.ON=0;
    T2CONbits.T32=1;        //Timers 2 y 3 como contadores de 32 bits
    TMR2=0;                 //Borro contenido de los registros del timer
    PR2=0x00002710;         //Cargo registros de comparación del timer (valor en el cual se resetea)
    IPC3SET = 0x00000004;   // Set priority level = 1
    IPC3SET = 0x00000001;   // Set sub-priority level = 1
                            // Could have also done this in single operation
                            // by assigning IPC5SET = 0x00000005
    IFS0bits.T3IF=0;        //Borro flag de interrupción
    IEC0bits.T3IE=1;        //Enable Timer5 interrupts
   
    IPC3bits.T3IP=7;        //Prioridad
    //IPC3bits.T3IS=3;        //Sub-prioridad
    T2CONbits.ON=1;         //Enciendo el timer
   
    //*******************************************************************
    //INTEnableSystemMultiVectoredInt();
    //INTEnableSystemSingleVectoredInt();
    INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
    INTEnableInterrupts();

   

    while(1)
     {
 
     }
}

void __ISR(_ADC_VECTOR,/*IPL6AUTO*/) ADCHandler(void)
{
    IFS0bits.AD1IF=0;       //Borro flag de interrupción
    /*T2CONbits.ON=0;
    TMR2=0;
    PR2=ADC1BUF0+0xFF;
    T2CONbits.ON=1;*/
}



void __ISR(_TIMER_3_VECTOR/*,IPL7AUTO*/) Timer3Handler(void)
{
        IFS0bits.T3IF=0;
        LATBbits.LATB14=!LATBbits.LATB14;
       
}

En lugar de controlar el Buzzer haciendo cambios al PR del Timer, voy a intentar ahora usar el PWM para ello, ya que la forma que intenté en primer lugar no esta funcionando. Y voy a seguir manteniendo varias interrupciones para verificar que no surjan nuevos problemas. Luego cuento como me fue.

¡¡Saludos!!
Cada esfuerzo por clarificar lo que es ciencia y de generar entusiasmo popular sobre ella es un beneficio para nuestra civilización global. Del mismo modo, demostrar la superficialidad de la superstición, la pseudociencia, el pensamiento new age y el fundamentalismo religioso es un servicio a la civilización.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con múltiples interrupciones en PIC 32
« Respuesta #8 en: 13 de Enero de 2013, 14:02:12 »
Respecto a esto Suky, tengo entendido que iplx (x es un numero del 1 al 7) define la prioridad de interrupción, pero si la tengo configurada mas arriba con la instrucción IPC3bits.T3IP=7 por ejemplo, esto es redundante, ¿O me equivoco?

Ese valor pasado al atributo de la función debe ser el mismo que el configurado en la interrupción. En MPLAB-XC32-Users-Guide hay más detalles.


Saludos!
No contesto mensajes privados, las consultas en el foro