Quote:
|
Originally Posted by tribotec_ca88
Inside the InterruptHandlerLow () function i've got the following IF loop set up:
if (PIR1bits.TMR1IF) // In other words, has Timer1 overflowed?
{
PIR1bits.TMRI1F = 0; // Resets Timer1
timer1_flag = 1; // Variable used as a flag
}
|
I'd suggest re-reading the PIC18F manual on TMR1 and looking over Kevin's code, you're close. At least from my experience.
In the ISR for the timer you'll need to reset the value in the timer. The timer, once enabled simply counts up to 0xFFFF and upon overflowing back to 0x0000 sets the TMR1F flag indicating overflow. It sets the flag whether interrupts are enabled or not. If interrupts are enabled for this timer, then the ISR is invoked. The timer however continues to get clocked and continues to count (0x0001, 0x0002, ... etc.) until it overflows again and another interrupt will be generated since the timer is still enabled. However in this case the time interval between the 1st interrupt and 2nd is however long it takes to count from 0 to FFFF vs the first time when it counted from 0x85ED to 0xFFFF. If you want a one shot interrupt, then you should disable the timer (T1CONbits.TMR1ON = 0) in the ISR.
If you want a periodic interrupt, then you'll need to reset the value in the timer to count from. For example, something like:
// timer continued to run on after it raised the interrupt
// latency is amount of count, save last latency in drift
timer1_drift.lo = TMR1L; // 16bit mode, read L -> latches H for reading
timer1_drift.hi = TMR1H;
// NOTE:
// Drift can be larger than 256 instructions if, for example,
// the timer interrupt is raised just after we test for it in
// the ISR and then spend a lot of time in the ADC or later
// interrupts - or high priority interrupt occurs - or ...
// So, do int arithmatic to compensate for drift.
timer1_drift.wrd += (0x85ED-13); // reload counter with desired value
// Note:
// Ideally we also add in a handful of cycles it takes to get from reading
// the timer above to resetting it here. Not many cycles but we can
// easily figure them out by looking at assembler and adjusting 0x85ED
// accordingly. I counted 13 cycles to be subtracted last time I checked
TMR1H = timer1_drift.hi;
TMR1L = timer1_drift.lo;
T1CON = 0x85; // reset prescaler, lost at TMR1L write time.
NOTE: The above logic might be wrong, it is mostly a copy of our sysclock routine which has a 1:1 prescaler vs this 1:8 prescaler. Therefore the (-13) cycles is not correct and should be adjusted as required.
Its also best to check that both the interrupt is enabled AND the interrupt flag is set:
if (PIR1bits.TMR1IF && PIE1bits.TMR1IE) ...
Regards,
DCBrown