Author: singularengineer

dsPIC/PIC24 Timers (using XC16 and MPLAB X)

In 8bit PIC, the timer interrupt happens when an overflow occurs. Therefore in order to get the required timing we set the starting value of the timer register in a way that overflow occurs at the required time.Which means we don’t usually start our count from 0. In dsPIC/PIC24 the timer starts from 0 and the overflow occurs at a value we set. This makes the calculations easy.

Timer1 in dsPIC is 16bit. The other timers (other than timer 1) are also 16 bit timers but can be combined to make it into 32bit timers. These timers are categorized into 3 types.

image

Each type has its advantages. Therefore select the timer to the need.

 

Documents to read

 

Before writing a topic, I try to read and make smaller notes so that I can skip going through the whole reference manual (unless I’m looking for some particular detail). But in this case microchip has done the best. Could just copy the whole pdf and put it here and call it a tutorial. That’s how good it is. So the pdf’s listed below based on the what chip is being used and the code snippet in the next section as a quick start.

 

For PIC24 (DS39704) – http://ww1.microchip.com/downloads/en/DeviceDoc/39704a.pdf 

For dsPIC (DS70205) – http://ww1.microchip.com/downloads/en/DeviceDoc/70205B.pdf

Timer library documentation is installed along with the compiler in your local machine. It can be found at C:\Program Files (x86)\Microchip\xc16\<compiler version>\docs\periph_libs\16-bit Peripheral Libraries.htm

Timer 1 Example (dsPIC 16 bit timer)

 

The part I’m using is dsPIC33FJ128GP202. The timer 1 is a 16bit timer. So I’m going to make the timer toggle an LED connected to RB0 for every 250ms.

My controller is running at 40MHz Fcy (Fcy = Fosc/2 ;  Fosc = 80MHz)

Calculation

 

With Prescale of 256

Value = period / (Prescale/ Fcy)

          = 0.250 / (256 / 40,000,000)

           = 39062.5

           = 39063 (roundup)

You need 2 functions

ConfigIntTimer1(T1_INT_PRIOR_1 & T1_INT_ON);

ConfigIntTimerx (x = 1,2,3…)

Priority 0 = equivalent of disable interrupt.

Priority 1 = highest priority

OpenTimer1(unsigned int t1config, unsigned int valueToMatch);

valueToMatch is what we calculated to be 39063. The t1config will have the settings to initialize the timer.

 

Timer 1 Code (dsPIC timer 1)

/* * File: dsPICtest.c * Author: Singular Engineer * * Created on July 12, 2014 */ #define FCY 40000000ULL //Fcy = (Fosc/2) Fosc = 80MHz #define _ISR_PSV __attribute__((__interrupt__, __auto_psv__)) #include <xc.h> #include "config.h" #include <libpic30.h> #include <timer.h> unsigned int valueToMatch = 0; void SetupClock(void); int main(int argc, char** argv) { SetupClock(); TRISBbits.TRISB0 = 0; //RB0 as output LATBbits.LATB0 = 1; //Turn on the led/RB0 valueToMatch = (unsigned int) 39063; ConfigIntTimer1(T1_INT_PRIOR_4 & T1_INT_ON); OpenTimer1(T1_ON & //Timer1 ON T1_GATE_OFF & //Gated mode OFF T1_IDLE_STOP & //Stop when controller is in sleep T1_PS_1_256 & //Prescale 256 T1_SYNC_EXT_OFF &// Don't sync with external clock T1_SOURCE_INT,valueToMatch); while(1) { } return 0; } void _ISR_PSV _T1Interrupt() { LATBbits.LATB0 = ~LATBbits.LATB0; //toggle RB0 pin IFS0bits.T1IF = 0; //clear T1 interrupt flagRead } void SetupClock() { //Setting N1 to 4 (N1 = n+2); n = N1-2 CLKDIVbits.PLLPRE0 = 0; CLKDIVbits.PLLPRE1 = 1; CLKDIVbits.PLLPRE2 = 0; CLKDIVbits.PLLPRE3 = 0; CLKDIVbits.PLLPRE4 = 0; //Setting M to 32 (M = m+2); m = M-2 PLLFBDbits.PLLDIV0 = 0; PLLFBDbits.PLLDIV1 = 1; PLLFBDbits.PLLDIV2 = 1; PLLFBDbits.PLLDIV3 = 1; PLLFBDbits.PLLDIV4 = 1; PLLFBDbits.PLLDIV5 = 0; PLLFBDbits.PLLDIV6 = 0; PLLFBDbits.PLLDIV7 = 0; PLLFBDbits.PLLDIV8 = 0; //Setting N2 to 2 CLKDIVbits.PLLPOST0 = 0; CLKDIVbits.PLLPOST1 = 0; }

In order to join two 16bit timers to act as a 32bit, instead of OpenTimer1 use OpenTimer23 to join Timer2 and Timer3 as 32bit timer.

 

Please feel free to use Microchip forums for questions http://www.microchip.com/forums/