C18 Timer0 cálculo de tiempo usando MCC18

4

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

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

Para usar TMR0 , he establecido lo siguiente:

  • Prescaler 1: 256
  • modo de 16 bits
  • Interrupción de alto nivel en TMR0 desbordamiento.

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

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

Entonces, TMR0 = 0xFFFF - 31250 .

¿Esto es 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 que se ejecute el método measure_and_switch() . ¿Debo seguirlo con WriteTimer0() ?

Btw: CLOCK_TICK es TMR0 (cálculo desde arriba).

Gracias

    
pregunta Buhake Sindi

1 respuesta

4

La respuesta es simple. Cuando se produce el bit de desbordamiento y se levanta la interrupción, primero debemos escribir el contador en TMR0 y restablecer el indicador TMR0IF .

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 cualquiera. :-)

    
respondido por el Buhake Sindi

Lea otras preguntas en las etiquetas