I'm trying to get the Timer2 period match interrupt on my dsPIC33FJ128GP802 working. I want it to interrupt after ~480 cycles. I'm using MPLAB C30.

I have, to initialize the timer and interrupt:

// Initialize Timer2, which is used for output timing.
T2CONbits.TON = 1;
T2CONbits.TSIDL = 0;
T2CONbits.TCKPS = 0;
T2CONbits.TCS = 0;
T2CONbits.T32 = 0;
// Initialize Timer2 interrupt with a slightly
// higher priority.
IPC1bits.T2IP = 5;
IFS0bits.T2IF = 0;
IEC0bits.T2IE = 0;

(the timer interrupt is initially disabled)

I have already got pin change interrupts working with a priority of 4. I want the Timer2 interrupt to have a higher priority.

And to set up the interrupt I have this:

T2CONbits.TON = 1;
TMR2 = 0;
timer2_osd = 480 + vid_hoffset;
PR2 = timer2_osd;
IEC0bits.T2IE = 1;

I also have an ISR,

void _MY_ISR _T2Interrupt()
    IFS0bits.T2IF = 0;

However I find the processor just resets and will not run with this enabled. It will work with a busy loop checking the timer, but that wastes cycles.

Can anyone see where I've gone wrong?

  • \$\begingroup\$ I assume _MY_ISR is defined as __attribute__((interrupt)) or similar? \$\endgroup\$
    – tcrosley
    Commented Nov 18, 2010 at 18:57
  • \$\begingroup\$ @tcrosley: correct \$\endgroup\$
    – Thomas O
    Commented Nov 18, 2010 at 19:10
  • \$\begingroup\$ If the processor is resetting only with your interrupt routine enabled, this is often a stack problem. You don't need the explicit return instruction, but it should be optimized out. In any case, you might want to look at the disassembly code (View -> Disassembly Listing) for the interrupt routine and post it. \$\endgroup\$
    – tcrosley
    Commented Nov 18, 2010 at 19:26
  • \$\begingroup\$ @tcrosley I've discovered it only crashes if I uncomment the PR2 statement. The code already has one interrupt which works perfectly, could it still be a stack issue? \$\endgroup\$
    – Thomas O
    Commented Nov 18, 2010 at 19:30
  • \$\begingroup\$ If the period register is 0, it probably never matches and so it never triggers the interrupt. With PR2 line uncommented, can you trigger on a breakpoint set inside the interrupt routine? \$\endgroup\$
    – tcrosley
    Commented Nov 18, 2010 at 19:42

2 Answers 2


I just looked at the code I wrote a while ago to set up timer 2 for a periodic interrupt of 1 ms for a PIC24F (essentially same timer hardware as dsPIC33F), and it looks like so:

#define CPU_CLK_RATE 32000000L

#define TIMER_2_RATE 1000L
#define TIMER_2_PRE  64L        // clock rate is (32000000/2)/64 = 250 KHz

    T2CON = 0; // set control register to defaults

    T2CONbits.TSIDL = 1;  // discontinue when idle
    T2CONbits.TCKPS1 = 1; // prescaler of 64
    T2CONbits.TCKPS0 = 0; // prescaler of 64
    T2CONbits.T32 = 0;    // 16 bit timer
    T2CONbits.TCS = 0;    // FOSC/2 (32Mhz/2)
    TMR2 = 0-TIMER_2_MATCH*19;  // 20 millisecond delay before starting
    PR2 = TIMER_2_MATCH; 

    SetPriorityIntT2(TIMER2_INTERRUPT_PRIORITY); // set to very high priority
    EnableIntT2; // enable interrupts

    T2CONbits.TON = 1

Very similar to yours, except I pre-initialized TMR2 so there would be a delay before the first interrupt. Don't know if that would help in your case or not, but you might try it.


The datasheet seems to suggest you should clear TON, initialize the timer, then set TON. Many example sequences end with setting TON, they don't start with it.

Many devices latch working values out of their configuration registers when they're enabled... so you should always disable, configure, then enable. Be very careful when changing registers on a running peripheral.

I'm also not clear on how the interrupt code gets tied to the timer2 interrupt event. What's _MY_ISR?

  • \$\begingroup\$ _MY_ISR is defined as __attribute__((interrupt, shadow, auto_psv)) \$\endgroup\$
    – Thomas O
    Commented Nov 18, 2010 at 19:13
  • \$\begingroup\$ I tried disabling the timer before config and then reenabling it but it doesn't work, and has the same problem (resetting I suspect.) \$\endgroup\$
    – Thomas O
    Commented Nov 18, 2010 at 19:13
  • \$\begingroup\$ @Thomas, since you are not accessing data in the auto_psv space in your interrupt routine, you can use no_auto_psv instead of auto_psv. \$\endgroup\$
    – tcrosley
    Commented Nov 18, 2010 at 19:30
  • \$\begingroup\$ @tcrosley: thanks for the suggestion but no luck... \$\endgroup\$
    – Thomas O
    Commented Nov 18, 2010 at 19:33
  • \$\begingroup\$ Perhaps it's my ignorance of that specific environment, but how does that interrupt routine get mapped to the timer2 overflow event? Usually there some vector table offset number, a name of the interrupt to tie to, etc. \$\endgroup\$
    – darron
    Commented Nov 18, 2010 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.