4
\$\begingroup\$

I am programming a PIC18F4520 and I've set it to use a 32Mhz internal clock.

I need a counter to tick every second so I'm using TMR0 for this purpose.

To use TMR0, I have set the following:

  • Prescaler 1:256
  • 16 Bit mode
  • High level interrupt on TMR0 overflow.

To set the timer to count every 1 second, I've calculated it as follows:

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

So, TMR0 = 0xFFFF - 31250.

Is this correct? If not, what am I missing? The code is as follows:

#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();
}

On my high level interrupt vector, I've done this:

#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.
    }
}

So, basically, every 2 minutes, I want the method measure_and_switch() to be executed. Should I follow it with WriteTimer0()?

Btw: CLOCK_TICK is TMR0 (calculation from above).

Thanks

\$\endgroup\$
  • \$\begingroup\$ Can you tell us what is happening now? I can't see that from the question itself. \$\endgroup\$ – AndrejaKo May 28 '12 at 0:05
  • \$\begingroup\$ My timer was off-course (clock ticks wasn't "synced"). I resolved it. Thanks. :-) \$\endgroup\$ – Buhake Sindi May 28 '12 at 0:24
  • \$\begingroup\$ Don't forget to post the solution as an answer and accept it after two days! \$\endgroup\$ – AndrejaKo May 28 '12 at 0:25
  • \$\begingroup\$ Sweet, will do. \$\endgroup\$ – Buhake Sindi May 28 '12 at 0:34
4
\$\begingroup\$

The answer is simple. When the overflow bit occurs and the interrupt is raised, we need to first write the counter to TMR0 and reset the TMR0IF flag.

This solution works:

#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.
    }
}

I hope this helps anyone. :-)

\$\endgroup\$
  • \$\begingroup\$ You should also check for TMR0IE before entering the function since it may be set even if you cleared the TMR0IE bit. \$\endgroup\$ – fhlb Mar 11 '16 at 12:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.