Based on information from IFI and Kevin Watson's sample code we figured out the value we needed to pre-load into the timer3 accumulator to make it overflow after 10ms. The formula (from IFI's whitepaper on timers) is:
number of ticks = (time elapsed) * 10^7/prescaler
number of ticks = (10/1000) * 10^7/8 = 12500
Since the counter overflows when it reaches 65535, you want to preload it with the difference. Therefore, the value is 65535 - 12500 = 53035. Converted to hex the value is 0xCF2B.
Using Kevin Watson's template we initialize timer3 using this code:
Code:
#define TIMER_LOW 0x2B
#define TIMER_HIGH 0xCF
void Initialize_Timer_3(void)
{
//preload the accumulator to overflow after 10ms
TMR3L = TIMER_LOW;
TMR3H = TIMER_HIGH;
//1:8 prescaler (clock=1.25MHz/each tick=800ns)
T3CONbits.T3CKPS0 = 1;
T3CONbits.T3CKPS1 = 1;
// 0: use the internal clock
T3CONbits.TMR3CS = 0;
// 1: synchronize the external clock to the PIC18F8520s internal clock, which is desirable //
T3CONbits.T3SYNC = 1;
/* timer 3 register operations are done in one 16-bit access */
T3CONbits.RD16 = 1;
/* 1: enable timer 3 interrupt on overflow (i.e., a transition from FFFF->0) */
PIE2bits.TMR3IE = 1;
/* 0: timer 3 overflow interrupt is low priority (leave at 0 on IFI controllers) */
IPR2bits.TMR3IP = 0;
/* timer 3 is enabled */
T3CONbits.TMR3ON = 1;
}
Don't forget to preload the accumulator for the timer again during the ISR. At the top of the function we just copied the first two lines of the initialization:
Code:
void Timer_3_Int_Handler(void)
{
/*reload the timer offset*/
TMR3L = TIMER_LOW;
TMR3H = TIMER_HIGH;
etc.
Since we need to do analog conversion during the ISR we made sure to disable the global interrupts in the main program before using the ADC. Setting INTCONbits.GIEL = 0 disables the low priority interrupts, then setting it back to 1 enables them.