Tuesday, September 2, 2008

PIC Interrupt Calculator & Code

I find that when writing interrupt code for the PIC Microcontrollers that it is often annoying figuring out the proper values for the overflow reset TMR0.
TMR0 (or any of the other timers) are incremented at a regular interval and when the value of the timer overflows the interrupt occurs. So if for example you used a Timer0 interrupt in 16bit mode with a prescaler of 1, then every 4 clock cycles of the main clock the value of TMR0 will increase by one and when it reaches 65536 the interrupt will happen.
If we want an interrupt to occur every 0.1 Seconds we would use a prescaler of 1:128 and 16bit mode. However instead of counting from 0x0000 to 0xFFFF, we will count from 0xDB61 to 0xFFFF. The calculator helps you figure out where to start counting from.
So, to make my life and yours easier, here is a Timer Calculator and example interrupt code.

PIC Timercalc for Google Docs

Example Interrupt Code

OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_128);
TMR0H and TMR0L are circled in red
The Prescaler is circled in blue and specified by TO_PS_1_128
TO_SOURCE_INT indicates the internal oscillator
16 bit Mode circled in green is indicated by T0_16BIT
Also please note that the accuracy column is not accurate, and the best way to calibrate the timing is to use the interrupt to blink an i/o line and connect it to an oscilloscope or use counter and a timer.
// Declare count as a global variablestatic unsigned int count = 0;// Function prototype for Intewrrupt service Routinevoid timer_isr(void);// Setup High and Low Priority Interrupt Vectors#pragma code high_vector = 0x000808void high_ISR (void){_asm goto timer_isr _endasm}#pragma code#pragma code _LOW_INTERRUPT_VECTOR = 0x000818void low_ISR (void){;}#pragma code#pragma interruptlow timer_isr// Primary Interrupt Service Routinevoid timer_isr (void){if (INTCONbits.TMR0IF) { // if Timer0 Interrupt has overflowedINTCONbits.TMR0IF = 0; // Reset overflow flag// 16 Bit Interrupts overflow at 65536// so if we start counting at 64536 it will take 1000 Clock "ticks" to overflowTMR0H = 0xDB;  // Timer0 High ByteTMR0L = 0x61;  // Timer0 Low Byte// This interrupt is designed to increment count every .1 Secondscount++;}}#pragma codevoid UserInit(void){//Enable Global InterruptsINTCONbits.GIE = 1;//Enable Priority InterruptsINTCONbits.PEIE = 1;TMR0H = 0xDB;  // Timer0 High ByteTMR0L = 0x61;  // Timer0 Low ByteOpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_128);/* more stuff here */}

No comments: