PIC Microcontoller Time Method

Timer tutorial (incl prescalers and interrupts)

Delays@

Andrew Warren [fastfwd at ix.netcom.com] of Fast Forward Engineering San Diego, California says:

Timer-0 has four components: The clock input (either from the TMR0 pin or from the internal instruction clock), the TMR0 prescaler, the TMR0 register, and the TMR0 interrupt flags (GIE, T0IE, and T0IF).

CLOCK INPUT:

You'll probably use the internal instruction clock as your TMR0 input; I'll assume that your PIC is running at 4 MHz. Since there's an internal divide-by-4 between the oscillator frequency and the instruction clock, this means that instruction clocks occur at a 1 MHz rate.

PRESCALER:

The TMR0 prescaler is set (via 4 bits in the OPTION register) to divide-by-1, -2, -4, -8, -16, -32, -64, -128, or -256. The TMR0 input clock (1 MHz in your case) is passed to the prescaler, whose divided-down output is then fed to the TMR0 register.

For example, if the TMR0 prescaler is set to divide-by-4 and the PIC is running at 4 MHz, the prescaler will send a 250 KHz clock to the TMR0 register.

TMR0 REGISTER:

The TMR0 register can be preloaded with any 8-bit value that you like.

Each clock pulse from the prescaler increments the contents of the TMR0 register. When the value in the TMR0 register rolls over from 0xFF to 0x00, the T0IF flag is set (the TMR0 register continues to be incremented on every pulse from the prescaler, though).

INTERRUPT FLAGS:

If the GIE and T0IE flags are set when the T0IF flag is set, an interrupt is generated (the GIE bit is automatically cleared (to temporarily prevent further interrupts while your interrupt routine is executing), and the PIC jumps to the "interrupt vector" at location 0x04. Your interrupt-service routine at that location should check the T0IF flag to determine the source of the interrupt, then must clear the T0IF flag to prevent the PIC from immediately jumping back to the interrupt routine when interrupts are re-enabled.

At this point in the interrupt routine, you can re-load the RTCC with any appropriate value.

When you're finished handling the interrupt, your code should execute a RETFIE instruction, which will automatically set the GIE bit to re-enable interrupts and return to your main program.

Luis F says:

If you want the delay in seconds:
Delay = (256 - InitTMR0 * prescaler)
            -----------------------------------------
                    Frequency / 4

Or if you want the value to put in TMR0 to get a determinate DELAY

InitTMR0 = 256 - ( DELAY * Frequency ) / ( 4* Prescaler)

For Accurate Period Timing

Bob Ammerman  or RAM Systems says:

What we really need is a way to ensure that Timer 1 interrupts every 5000 instructions or 1 millisecond.

The problem is that there can be jitter on reaching the interrupt handler for the timer. This jitter is caused by 2-cycle instructions, other interrupt handlers, and interrupts being disabled at 'task' level.

We can get around the jitter problem by always adding a constant to the timer, rather than trying to set it directly. What we are doing is effectively advancing time forward the rest of the 65536-5000 instructions to get the timer to interrupt again at the right point.

Here is my suggestion (this code would be in the interrupt handler)

fudge = ...number to account for instructions timer is turned off...
magic_value = D'65536'-D'5000'+fudge

    bcf        T1CON,TMR1ON    ; turn off timer
    movlw   low(magic_value)
    addwf   TMR1L,F
    btfsc     STATUS,C
    incf       TMR1H,F
    movlw   high(magic_value)
    addwf   TMR1H,F
    bsf        T1CON,TMR1ON    ; turn it back on

Dan Michaels of Oricom Technologies says:

With Timer1, try using the "special event trigger" interrupt mode - selected by CCP1CON = xxxx1011. This way you initialize Timer1 once, and the value acts as the interrupt "period".

I assume '87x work the same as older '7x chips.

Josef of Snail Instruments [snail at IOL.CZ] says:

Using the compare register is the way to go. Set no prescaler on TMR1, set the CCP module for the special event and load CCPxL & CCPxH register pair with the desired period _MINUS ONE_. Just make sure you substitute CCPxIF for TMR1IF (TMR1IF never gets set, since TMR1 never overflows). Both CCP1 and CCP2 work equally well.

Interested:

Questions:

Comments:

Archive:

Code: