• AVR Freaks

Hot!TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interrupt

Author
jpdesroc
Starting Member
  • Total Posts : 83
  • Reward points : 0
  • Joined: 2011/01/31 11:20:06
  • Location: 0
  • Status: offline
2020/06/29 08:56:22 (permalink)
0

TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interrupt

Perhaps this will be an easy one for you
but I cannot figure out the problem..
MPLAB X IDE v5.20, ICD3, HiTech PICC 9.83 C compiler
PIC16F88 using:
Internal 8Mhz clock
A/D converter on AN0
TIMER1 to generate pulses on
PORTB RB0,1,2,3,4

I read the ADC input (AN0) and use the 10bits value
to change the starting TIMER1 16bits register value
before it reach 0xFFFF and triggers another interrupt (TMR1IF flag).
Everything works fine but after about 3 minutes
The interrupt function stops clearing the TMR1IF flag
before exiting the interrupt function (!!!)
Since the TIMER1 interrupt flag kept its set value
the interrupt is not called anymore and the output pulses stop..
I tried to place the TMR1IF = 0; line at the beginning and
at the far end of the interrupt function
but still the same behaviour..
I thought this could be the RBIE (RB Port Change Interrupt Enable bit)
so I reset it at the beginning of the program
but still no changes..

This is a small program and it's listed below.
I hope someone will see the problem.. So far I cannot.
Jean-Pierre



#include <pic.h>

 // Internal 8Mhz clock
    __CONFIG( FOSC_INTOSCIO & LVP_OFF & WDTE_OFF & PWRTE_OFF & BOREN_OFF & CP_OFF & MCLRE_ON );
    __CONFIG( FCMEN_OFF & IESO_OFF);
    
#define _XTAL_FREQ 8000000
 
#define FALSE 0
#define TRUE 1

#define TMR1_60HZ_START_VAL 0xDF60 // From 0xDF60 to 0xFFFF TMR1 counts 1 of the four 16.66msec. steps giving 60Hhz
#define TMR1_POT_MULTIPLIER 41     // Pot value multiplied by this strech each steps to 25msec. giving 10Hz
volatile unsigned int new_tmr1_val;
volatile unsigned char new_tmr1_lo, new_tmr1_hi;
volatile unsigned char pulse_step;

////////// Fonctions Prototypes /////////
void init_A_to_D(void);
unsigned int read_AD(unsigned char channel);

void init_TIMER1(void);

///////////////////////////////
// ----------------------------
//  interrupt service routine
// ----------------------------
///////////////////////////////                              

void interrupt tmr1_isr (void)
 {

  // Timer1 interrupt every 4.166msec (1/60hz div by 4 steps)
  if (TMR1IF == TRUE)
   {       
    // restart TIMER1 with basic 0xDF60 value + speed pot val added..
    // Timer1 restart values before reaching 0xFFFF for next TMR1 interrupt.
    // Internal 8Mhz clock divided by 4 = TMR1 clock @ 2Mhz (0,5usec period)
    // 0,5usec x 0x209F = 4,166msec steps @ 60Hz pot position
    // 0,5usec x 0xC9A6 = 25msec. steps @ 10Hz pot position
    
    TMR1H = new_tmr1_hi; // 0xFFFF - 0xDF60 = 0x209F => per steps = 4.166msec.
    TMR1L = new_tmr1_lo; // 0xFFFF - 0x3659 = 0xC9A6 => per steps = 25msec.
                         // 0xC9A6 - 0x209F = 0xA907 (to be covered by pot)

    //  |  step0 |  step1 |  step2 |  step3
    //  |4.16msec|4.16msec|4.16msec|4.16msec
    //  |        |        |        |
    // _|--------|___________________________ RB0
    // ___________________|--------|_________ RB1   
        
    pulse_step++;
    if(pulse_step==4) pulse_step=0; // steps: 0,1,2,3

    switch (pulse_step)
     {
      case 0:
        PORTB = 0b00000101;
        break;
              
      case 1:
        PORTB = 0b00000100;
        break;             
              
      case 2:
        PORTB = 0b00001010;
        break;
              
      case 3:
        PORTB = 0b00001000;
        break;
            
      default:
        break;             
       }
    
      new_tmr1_val = 1023 - read_AD(0); // Speed 10bits res. (read_AD() = 372 usec. read function time)
      new_tmr1_val *= TMR1_POT_MULTIPLIER;
      new_tmr1_val = TMR1_60HZ_START_VAL - new_tmr1_val;
     
      // prepare new TMR1 values for next interrupt..
      new_tmr1_hi = (unsigned char) (new_tmr1_val>>8);
      new_tmr1_lo = (unsigned char) (new_tmr1_val & 0x00FF);   
   
      TMR1IF = 0;  // <---------------------    
      
    } // if (TMR1IF == TRUE)
    

   }



void main()             
{
 OSCCON = 0B01110110;   // Internal 8Mhz RC clock
 ANSEL = 0b00000001;    // Bits7..1 Digital outputs, bit0 as A/D input
 TRISA = 0b00000001 ;   // set PORTA bits 7..1 as output, bit0 = A/D input
 TRISB = 0 ; // set PORTB as output
 PORTB = 0 ; // clear all PORTB pins

 init_A_to_D();
 init_TIMER1();
        
 PEIE = 1; // Authorize peripherals interrupt
 GIE =1;   // Authorize global interupt

 while(1)
  {
   ;  
   //  All happens in the TIMER1 interrupt function..
  }

} // main()
     
//////////////// Routines /////////////////////

void init_TIMER1(void)
{
 // Configuration TIMER1

 T1CON = 0b00000101; // 1:1 prescale @ 8Mhz, Fosc/4, TIMER1 ON
 TMR1H = 0;
 TMR1L = 0;

 TMR1IE = 1; // Enable TIMER1
}

///////////////////////////////////////////////
///////////////////////////////////////////////
void init_A_to_D(void)
{
 ADCON0 = 0b10000001; // Fosc/32, A/D channel=0, AD ON
 ADCON1 = 0b00000100; // Left justified, A/D inputs 0,1,3
}

///////////////////////////////////////////////
unsigned int read_AD(unsigned char channel)
{
 unsigned int result;

 ADCON0 &= 0b11000111; // mask channel select bits
 ADCON0 |= (channel << 3);
 __delay_us(10); // Wait for DC in stabilisation  
 GO = 1; // Start conversion
 while(GO) // Wait for conversion done
  continue;

 result = ADRESH;
 result <<= 2;
 result += (ADRESL>>6);  

 return(result); // 10 bits result...
}



#1

11 Replies Related Threads

    1and0
    Access is Denied
    • Total Posts : 10987
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 09:52:42 (permalink)
    0
    jpdesroc
    Everything works fine but after about 3 minutes
    The interrupt function stops clearing the TMR1IF flag
    before exiting the interrupt function (!!!)
    Since the TIMER1 interrupt flag kept its set value
    the interrupt is not called anymore and the output pulses stop..


     ADCON1 = 0b00000100; // Left justified, A/D inputs 0,1,3


     result = ADRESH;
     result <<= 2;
     result += (ADRESL>>6);  

     return(result); // 10 bits result...
    }

    I think your problem is elsewhere, because if TMR1IF is not cleared the ISR will be executed continuously changing your output pulses very fast.  Also, why not use right-justified A/D result?
    #2
    jpdesroc
    Starting Member
    • Total Posts : 83
    • Reward points : 0
    • Joined: 2011/01/31 11:20:06
    • Location: 0
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 10:34:06 (permalink)
    0
    Update...,
    I programmed (production .HEX) the PIC16F88 and removed it
    from the MPLAB X IDE debugger environment and now it does not stop
    as it did in a debug envir. Steady running as it should.
    This seems to be a recurrent 'timeout' in the MPLAB X IDE debugger behaviour (??)
    Anybody has a clue on that ?
    And about the A/D left-justified I chose.. This is because doing so
    this aligns the AD 10bits the same way the left-justified TIMER1 registers TMR1H, TMR1L are.
    #3
    1and0
    Access is Denied
    • Total Posts : 10987
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 12:07:48 (permalink)
    +1 (1)
    jpdesroc
    And about the A/D left-justified I chose.. This is because doing so
    this aligns the AD 10bits the same way the left-justified TIMER1 registers TMR1H, TMR1L are.

    Come again?  Your A/D is configured to return a left-justified result, but your A/D function manually right-justifies that.
    #4
    jpdesroc
    Starting Member
    • Total Posts : 83
    • Reward points : 0
    • Joined: 2011/01/31 11:20:06
    • Location: 0
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 12:25:01 (permalink)
    0
    1and0
    Come again?  Your A/D is configured to return a left-justified result, but your A/D function manually right-justifies that.

     
    My A/D returns a 0 to 0x3FF left-justified value normally but I needed
    a 0x3FF to 0 behaviour with the pot.. so:
     
    new_tmr1_val = 1023 - read_AD(0);
     
    new_tmr1_val is still left justified but from 0x3FF to 0
    as 0 for the max pot value instead of 0x3FF.
    Everything here is left-justified. In fact the final
    calculation put in the TMR1HI & TMR1LO
    at the beginning of the function needs to be kept left-justicfied to work
    and it works.
     
    #5
    1and0
    Access is Denied
    • Total Posts : 10987
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 12:31:06 (permalink)
    +1 (1)
    jpdesroc
    My A/D returns a 0 to 0x3FF left-justified value normally but I needed
    a 0x3FF to 0 behaviour with the pot.. so:
     
    new_tmr1_val = 1023 - read_AD(0);
     
    new_tmr1_val is still left justified but from 0x3FF to 0
    as 0 for the max pot value instead of 0x3FF.
    Everything here is left-justified. In fact the final
    calculation put in the TMR1HI & TMR1LO
    at the beginning of the function needs to be kept left-justicfied to work
    and it works.

    I'm not trying to be mean, but do you know LEFT from RIGHT ??
     
    #6
    jpdesroc
    Starting Member
    • Total Posts : 83
    • Reward points : 0
    • Joined: 2011/01/31 11:20:06
    • Location: 0
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 12:55:42 (permalink)
    0
    >I'm not trying to be mean, but do you know LEFT from RIGHT ??
    LOL.... Maybe I need another cofee this afternoon..
    If I say the reading of the pot is 0x3FF and I use it as
    binary 0000 0011 1111 1111 .. Is this left justified ?
    I'm probably mixing things here..
    Does left-justified means MSB are first read
    in a serial reading or is-it right ? Sorry.
    #7
    1and0
    Access is Denied
    • Total Posts : 10987
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 13:06:30 (permalink)
    +1 (1)
    jpdesroc
    >I'm not trying to be mean, but do you know LEFT from RIGHT ??
    LOL.... Maybe I need another cofee this afternoon..
    If I say the reading of the pot is 0x3FF and I use it as
    binary 0000 0011 1111 1111 .. Is this left justified ?
    I'm probably mixing things here..
    Does left-justified means MSB are first read
    in a serial reading or is-it right ? Sorry.

    A 10-bit A/D value left-justified is HHHH HHHH LL00 0000 with a range of 0x0000 to 0xFFC0, and a right-justified value is 0000 00HH LLLL LLLL with a range of 0x0000 to 0x03FF.
     
    #8
    upand_at_them
    Super Member
    • Total Posts : 579
    • Reward points : 0
    • Joined: 2005/05/16 07:02:38
    • Location: Pennsylvania
    • Status: online
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 13:13:45 (permalink)
    +2 (2)
    The purpose of left-justifying a 10-bit value is that you move the top 8 bits of the result into the HIGH register and read just that 8-bit value.  You lose the bottom two bits, but in a lot of cases that may not matter and dealing with just one byte is easier.  So you wind up with a 0x00 to 0xFF value by just reading the HIGH register.
    post edited by upand_at_them - 2020/06/29 13:17:20
    #9
    jpdesroc
    Starting Member
    • Total Posts : 83
    • Reward points : 0
    • Joined: 2011/01/31 11:20:06
    • Location: 0
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 13:21:41 (permalink)
    0
    1and0
    A 10-bit A/D value left-justified is HHHH HHHH LL00 0000 with a range of 0x0000 to 0xFFC0, and a right-justified value is 0000 00HH LLLL LLLL with a range of 0x0000 to 0x03FF.



    Good  explaination..
    Understood !
    I'll need to get into my code to see why it's working...
    #10
    1and0
    Access is Denied
    • Total Posts : 10987
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/29 13:33:42 (permalink)
    0
    jpdesroc
     
    Good  explaination..
    Understood !
    I'll need to get into my code to see why it's working...

    My point is if the A/D is configured to return a right-justified result, it is more efficient to read as
    result = (ADRESH << 8) | ADRESL;

    or better yet
    return ((ADRESH << 8) | ADRESL);

    in your function.
    #11
    jpdesroc
    Starting Member
    • Total Posts : 83
    • Reward points : 0
    • Joined: 2011/01/31 11:20:06
    • Location: 0
    • Status: offline
    Re: TIMER1 interrupt stops to be called on PIC16F88.. TMR1IF stops to be cleared in interr 2020/06/30 05:37:40 (permalink)
    +1 (1)
    My first main issue was:
    Why MPLAB X IDE stops running the 'in debugging' program after around 3 minutes ?
    This was always caused by the TMR1IF stopping to be cleared in the TMR1 only interrupt function.
    When I burn the PIC16F88 with the 'production' HEX file and disconnect it
    from MPLAB X the program runs continuously and normnally.. (??)
    #12
    Jump to:
    © 2020 APG vNext Commercial Version 4.5