Strange interrupt behavior. XC8 V2.0 PIC16F1619

Thread Starter

odm4286

Joined Sep 20, 2009
250
I'm having a strange problem I can't wrap my head around. It's easiest to explain with some code first.

Here is a while loop that I want to use to keep the software at a certain point while my timer ISR increments a counter.

Code:
run_duration = 0;                                           // reset run_duration 
T1CONbits.TMR1ON = 1;                              // turn on timer1
while(run_duration <= pwm_run_time);            // hang out here until the duration is up. 
T1CONbits.TMR1ON = 0;                              // turn off timer1
change_duty(PWM_OFF);                              // turn off PWM. 0 percent duty cycle
Here are my ISRs and the volatiles
Code:
// volatiles 
volatile unsigned int mS_count = 0;
volatile unsigned int run_duration = 0;
volatile unsigned int pwm_run_time = 0;
volatile unsigned char receive_mode = 0;
volatile unsigned char packet[PACKET_SIZE];
volatile unsigned char received_bytes = 0;
volatile unsigned char transmit_bool = 0;



// Master ISR
void __interrupt() master_isr()                                         // Single interrupt vector on this chip I think
{
   
    if(PIR1bits.TMR1IF)                                                   // keeps track of PWM run time
    {
        PIR1bits.TMR1IF = 0;                                             // clear the flag
        TMR1L = (unsigned char)(0xFF & TIMER_ONE_PREFILL);                        // grab timer1 prefill low byte
        TMR1H = (unsigned char)(0xFF00 & TIMER_ONE_PREFILL);                    // grab timer1 prefill high byte
        //++run_duration;
    }
   
    if(INTCONbits.T0IF)                                                    // handles my heartbeat
    {
        INTCONbits.T0IF = 0; 
        ++mS_count; 
        ++run_duration;
        TMR0 = TIMER_ZERO_PREFILL;
        heartbeat(&mS_count);                                           // not a big fan of calling a function inside of an ISR but oh well...
    } 
     
    if(PIR5bits.TMR3IF)                                                    // transmit idle clock. Tx every 250mS
    {
        PIR5bits.TMR3IF = 0;
        TMR3L = (unsigned char)(0xFF & TIMER_THREE_PREFILL);                    // grab timer3 prefill low byte
        TMR3H = (unsigned char)(0xFF00 & TIMER_THREE_PREFILL);                // grab timer3 prefill high byte
        transmit_bool = 1;
    }
   
    if(PIR1bits.RCIF)                                                            // receive interrupt 
    {
        PIR1bits.RCIF = 0;                                                      // clear flag
        receive_mode = 1;                                                      // set receive mode
        packet[received_bytes] = receive_data();                     // get data
        ++received_bytes;                                                      // increment the number of bytes we've received 
    }
}
Now the strange part is that when I increment run_duration inside the TIMER1 ISR my program just hangs at that while loop forever as far as I can tell. However, if I increment in timer0 ISR everything runs just as I would expect it to.

Here is what I did to troubleshoot so far. I'm at a loss, any ideas?
- toggled an output pin inside tmr1 isr. It's firing and on my scope the timing is exactly what I want it to be.
- ran this through a debugger, run_duration increments in both ISRs
 

AlbertHall

Joined Jun 4, 2014
11,238
I don't know if this is anything to do with your problem but this line:
TMR1H = (unsigned char)(0xFF00 & TIMER_ONE_PREFILL);
will not load TMR1H with the high byte of TIMER_ONE_PREFILL as it is apparently intended to do.

Try:
TMR1H = (unsigned char)((0xFF00 & TIMER_ONE_PREFILL)>>8);

[EDIT] Or, probably better, use separate single byte prefills for the high and low byte.
TMR1L = Prefill_l;
TMR1H = Prefill_H;
 
Top