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
Best Answer
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 theTMR0IF
flag.This solution works:
I hope this helps anyone. :-)