C18 Cálculo de temporización de Timer0 utilizando MCC18

Estoy programando un PIC18F4520 y lo configuré para usar un reloj interno de 32Mhz.

Necesito un contador para marcar cada segundo, así que lo estoy usando TMR0para este propósito.

Para usarlo TMR0, he configurado lo siguiente:

  • Preescalador 1:256
  • Modo de 16 bits
  • Interrupción de alto nivel en TMR0desbordamiento.

Para configurar el temporizador para que cuente cada 1 segundo, lo calculé de la siguiente manera:

TMR0 = (Required time)/(4 * Timer clock * prescale value)
     = 1 / (4  * (1/32000000) * 256)
     = 31250

Entonces, TMR0 = 0xFFFF - 31250.

¿Es esto correcto? Si no, ¿qué me estoy perdiendo? El código es el siguiente:

#pragma code
void main(void)
{
    //Set clock frequency
    OSCCON |= 0x70;             //8 Mhz clock, primary clock
    OSCTUNEbits.PLLEN = 1;          //4x Multiplier, thus we have 32 Mhz clock
    while (!OSCCONbits.IOFS);       //Wait until INTOSC is stable.

    //Enable TRISA as analog input (For ADC)
    TRISA = 0x2F;

    //PIN Outputs
    TRISB = 0;              //Make PORTD as output
    //Reset PORTB
    PORTB = 0;

    //Set ADC
    OpenADC(ADC_FOSC_32 &           //Fosc/32
         ADC_RIGHT_JUST &
         ADC_4_TAD,             //4xTAD
         ADC_CH0 &
         ADC_REF_VDD_VSS &
         ADC_INT_OFF, ADC_5ANA);        //ADC CH0-CH4 Initialized

    //Set Timer0
    OpenTimer0( TIMER_INT_ON &
                T0_16BIT &
                T0_SOURCE_INT &
                T0_PS_1_256);

    //Write Timer
    WriteTimer0(CLOCK_TICK);

    INTCON2bits.TMR0IP = 1;         //TMR0 has high overflow interrupt priority
    RCONbits.IPEN = 1;                  //enable priority levels
    INTCONbits.GIEH = 1;            //enable high interrupts

    //Begin
    while (TRUE)
    {

    }

    CloseADC();             //Closing ADC
    CloseTimer0();
}

En mi vector de interrupción de alto nivel, he hecho esto:

#pragma code 
#pragma interrupt high_priority_interrupt 
void high_priority_interrupt()
{
    if (INTCONbits.TMR0IF)                  //TIMER0 overflowed
    {
        //Stuff
        second += 1;
        if (second == 60)
        {
            minute += 1;
            second = 0;
        }

        if (minute == 60)
        {
            measure_and_switch();
            WriteTimer0(CLOCK_TICK);
            minute = 0;
        }

        INTCONbits.TMR0IF = 0;              //Clear TIMER0 overflow bit.
    }
}

Entonces, básicamente, cada 2 minutos, quiero measure_and_switch()que se ejecute el método. ¿Debo seguirlo con WriteTimer0()?

Por cierto: CLOCK_TICKes TMR0(cálculo desde arriba).

Gracias

¿Puedes decirnos qué está pasando ahora? No puedo ver eso de la pregunta en sí.
Mi temporizador estaba fuera de curso (los tictacs del reloj no estaban "sincronizados"). Lo resolví. Gracias. :-)
¡No olvide publicar la solución como respuesta y aceptarla después de dos días!
Dulce, lo haré.

Respuestas (1)

La respuesta es simple. Cuando ocurre el bit de desbordamiento y se activa la interrupción, primero debemos escribir el contador TMR0y restablecer la TMR0IFbandera.

Esta solución funciona:

#pragma code 
#pragma interrupt high_priority_interrupt 
void high_priority_interrupt()
{
    if (INTCONbits.TMR0IF)              //TIMER0 overflowed
    {
        //Stuff
        second += 1;
        if (second == 60)
        {
            minute += 1;
            second = 0;
        }

        if (minute == 60)
        {
            measure_and_switch();
            minute = 0;
        }

        WriteTimer0(CLOCK_TICK);        //Write the count to TMR0.
        INTCONbits.TMR0IF = 0;          //Clear TIMER0 overflow bit.
    }
}

Espero que esto ayude a alguien. :-)

También debe verificar TMR0IE antes de ingresar a la función, ya que puede establecerse incluso si borró el bit TMR0IE.