interrumpir usando Timer0 en PIC18f

4

Estoy buscando un poco de ayuda y consejos sobre mi código.

Estoy usando C18 en el entorno MPLab, PIC18f4520 con Fosc a 4MHz, y usnig timer0 en modo de 16 bits para contar el desbordamiento, establecer el bit de desbordamiento y el indicador de interrupción, luego saltar a ISR e incrementar una variable 'conteo'. Esto se envía a un puerto con indicadores LED conectados para que pueda obtener una confirmación visual del funcionamiento del programa.

Sin embargo, el recuento generado siempre es '1' (es decir, 0x01) y creo que el ISR solo ocurre una vez, en todo caso.

Cualquier ayuda que pueda ofrecer sería muy apreciada.

Aquí está mi código:

void main (void)        /*                                                                                      */
{                   
TRISA = 0;          /*                                                                                      */
TRISC = 0;          /*                                                                                      */
TRISB = 0;
TRISD = 0x00;
RTOS();
}
void low_interrupt (void)
    {
    _asm GOTO timer_isr _endasm
    }
    #pragma code
    #pragma interruptlow timer_isr 

void timer_isr (void)
    {
    INTCONbits.TMR0IF = 0;
    count = count++;
    LATD = count;
    RTOS();
    }
void RTOS (void)
    {
    T0CONbits.T08BIT = 0;   // 16-bit timer
    T0CONbits.T0CS = 0;     // increment on instruction cycle input
    T0CONbits.T0SE = 0;     // increment on low--> high transition of clock
    T0CONbits.PSA = 1;      // T0 prescaler not assigned i.e. 1:1 prescaler.
    RCONbits.IPEN       = 1;    //Enable Interrupt Priorities
    INTCONbits.GIEL     = 1;    //Enable Low Priority Interrupt
    INTCONbits.GIE      = 1;    //Enable Global Interrupts            
    INTCONbits.TMR0IE   = 1;    //Enable Timer0 Interrupt
    INTCON2bits.TMR0IP  = 0;    //TMR0 set to Low Priority Interrupt
    INTCONbits.TMR0IF = 0;  // T0 int flag bit cleared before starting
    T0CONbits.TMR0ON = 1;   // timer0 START
    while (1);
    }

Gracias de antemano por cualquier orientación que pueda ofrecer.

    
pregunta Mondogenerator

3 respuestas

4

Está llamando a RTOS () en su interrupción y la función RTOS () tiene "while (1);" en ella (¿bucle infinito?)

No estoy seguro de por qué restablecería los registros de interrupción completos dentro de su interrupción.

Tener un bucle infinito en tu interrupción probablemente hará que tu programa no funcione correctamente.

También, verifique el comentario de Roger Rowland: "¿Dónde está definido count ? ¿Lo ha marcado volatile ? - Roger Rowland hace 15 minutos". Este es un error bastante común y también podría ser el punto aquí.

    
respondido por el Paul
2

No estoy familiarizado con C18, pero uso su sucesor XC8.

Con respecto a su ISR, ¿sabe el compilador C18 que ejecute void low_interrupt (void) cuando se genera una interrupción de baja prioridad? He visto funciones designadas para interrupciones con algunos compiladores, pero XC8 funciona de la siguiente manera:

// HP int declared with 'high_priority' identifier, name function as you see fit
interrupt high_priority void isr_high(void)

// LP int declared with 'low_priority' identifier, name function as you see fit
interrupt low_priority void isr_low(void)

Si C18 usa nombres de funciones designados, asegúrate de que los tienes correctos.

En segundo lugar, así es como habría manejado el desbordamiento de tu temporizador:

interrupt high_priority void isr_high(void)
{  
    // TIMER0 Overflow
    if (INTCONbits.TMR0IF)
    {
        LATEbits.LE0 ^= 1;               // Toggle RE0
        INTCONbits.TMR0IF = 0;           // Clear the interrupt flag
    }
}

Espero que esto ayude.

    
respondido por el Brian J Hoskins
0

Gracias por toda la ayuda.

Con un poco de trabajo en MPLabSim, encontré mi error y el código corregido a continuación funciona correctamente, al menos en MPLabSim:

EDITAR: ¡ahora también funciona en hardware real!

 void main (void)       /*                                                                                      */
    {                   
    TRISA = 0;          /*                                                                                      */
    TRISC = 0;          /*                                                                                      */
    TRISB = 0;
    TRISD = 0x00;
    RTOS();
    }
void low_interrupt ()
    {
    _asm GOTO timer_isr _endasm
    }
    #pragma code
    #pragma interrupt low_interrupt //save =PROD
void timer_isr ()
    {
    if(INTCONbits.TMR0IF==1)
    {
    count++;
    INTCONbits.TMR0IF = 0;
    }
    }
void RTOS ()
    {
    T0CONbits.T08BIT = 0;   // 16-bit timer
    T0CONbits.T0CS = 0;     // increment on instruction cycle input
    T0CONbits.T0SE = 0;     // increment on low--> high transition of clock
    T0CONbits.PSA = 1;      // T0 prescaler not assigned i.e. 1:1 prescaler.
    RCONbits.IPEN       = 1;    //Enable Interrupt Priorities
    INTCONbits.GIEL     = 1;    //Enable Low Priority Interrupt
    INTCONbits.GIEH     = 0;    // disable high priority interrupts
    INTCONbits.GIE      = 1;    //Enable Global Interrupts            
    INTCONbits.TMR0IE   = 1;    //Enable Timer0 Interrupt
    INTCON2bits.TMR0IP  = 0;    //TMR0 set to low Priority Interrupt

    INTCONbits.TMR0IF = 0;  // T0 int flag bit cleared before starting
    T0CONbits.TMR0ON = 1;   // timer0 START
    counter(count);
    }   
void counter ()
{
LATD = count;
}   
    
respondido por el Mondogenerator

Lea otras preguntas en las etiquetas