PIC18F45K22 Timer1 Assistance required

Thread Starter

GettinBetter

Joined Jun 22, 2018
42
Hi Guys,
Been working on this all day.. well I say all day but updating the IDE seemed to break everything, then later updating XC8 broke stuff again.
All good fun though....but there comes a point when you need to ask for help, so I am :D
I'm trying to read PORTB into a var and then eventually out to term'....as it wasn't working I started to strip bits of code out till I was just getting TMR1 to work....but it isn't. Here's the code. (MPLABX ver5.0, DEV Board - EasPICV7 , Comp- XC8 ver2.0, Debug - ICD3)

Code:
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();
   
    unsigned char temp;
    unsigned int countTMR1IFs=0;
   
    void TMR1_Initialize(void);
    void TMR1_StartTimer(void);
    void INTERRUPT_Initialize (void);
              
    while (1)
    {
        if (PIR1bits.TMR1IF)    //If flagged run ISR
          {
    void TMR1_ISR(void);        // Calling ISR
    void TMR1_StartTimer(void); // & restart timer
            }
        }
/*
    ************* END OF MAIN ****************
*/
        void TMR1_ISR(void);
        {
            countTMR1IFs++;     // TMR1 Flagged count number of times
            if (countTMR1IFs==10) // Too slow for application, but it's fine for testing.
            {
            temp=PORTB;             // After flagging 10 times read PORTB
            countTMR1IFs=0;         // reset counter
            }
        PIR1bits.TMR1IF = 0;        // Reset flag
        }
}
/**
End of File
*/
Any feedback would be appreciated.
Regards
Les
 

Thread Starter

GettinBetter

Joined Jun 22, 2018
42
Cheers nsaspook, Good video for me (as a noob)...I think I've tweaked my effort to include info garnished from the vid.... Now if I step it through it gives the result I was expecting. The watch window shows each pin high (when I push the button on my dev board) and step through. However when I run it (in debug) pushing of the button doesn't go high in the watch window. Neither does the 'countTMRIFs' variable increment. I'm thinking the timers not actually running, as the "if (INTCONbits.GIE && PIR1bits.TMR1IF)" never actually triggers.
I'm getting to the stage where I can't see for looking.
Modified code below....
Code:
#include "mcc_generated_files/mcc.h"

/*
    ************* START OF MAIN ****************
*/
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();
   
    unsigned char temp;
    unsigned int countTMR1IFs=0;
   
    void TMR1_Initialize(void);
    void TMR1_StartTimer(void);
    void INTERRUPT_Initialize (void);
              
    while (1)
    {
        if (INTCONbits.GIE && PIR1bits.TMR1IF)      //If flagged run ISR
          {
           INTCONbits.GIE =0;                       // disable Global Interrupts
    void __interrupt () myTMR1_ISR(void);           // Calling myISR
    INTCONbits.GIE =1;                              // Re-enable Global Interrupts

            }
        }
/*
    ************* END OF MAIN ****************
*/
        void __interrupt() myTMR1_ISR(void);
        {
            countTMR1IFs++;     // TMR1 Flagged count number of times
            if (countTMR1IFs==10) // Too slow for application, but it's fine for testing.
            {
            temp=PORTB;             // After flagging 10 times read PORTB
            countTMR1IFs=0;         // reset counter
            }
        PIR1bits.TMR1IF = 0;        // Reset flag
        }
}
/**
End of File
*/
odified code....
 

nsaspook

Joined Aug 27, 2009
13,086
You main code should NEVER try to directly execute the interrupt code so you should remove the entire 'if' statement from the while(1) loop. Variables temp and countTMR1IF should have the volatile qualifier because they are being modified out of normal program flow in myTMR1_ISR (Global variables modified by an interrupt service routine).
 

Thread Starter

GettinBetter

Joined Jun 22, 2018
42
LOL, my latest efforts....:D ..I'm thinking there's nothing to do except run the timer and do the ISR? Now if I pause the prog in debug the watch window shows the timer running, but the ISR test conditions never seem to be met!


Code:
#include "mcc_generated_files/mcc.h"

/*
    ************* START OF MAIN ****************
*/
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();

    INTERRUPT_GlobalInterruptEnable();      // Enable the Global Interrupts
    INTERRUPT_PeripheralInterruptEnable();  // Enable the Peripheral Interrupts
  
    unsigned char volatile temp;
    unsigned int volatile countTMR1IFs=0;
  
    void TMR1_Initialize(void);         // Initialise timer1
    void INTERRUPT_Initialize (void);   // Initialise Interrupts
    void __interrupt() INTERRUPT_InterruptManager (void);
    void TMR1_StartTimer(void);        // Start timer1 running
    while (1)
    {

    }
/*
    ************* END OF MAIN ****************
*/
        void TMR1_ISR(void);
        {
            if(PIE1bits.TMR1IE == 1 && PIR1bits.TMR1IF == 1)      //When ISR called check it's the one I want
            {
                PIE1bits.TMR1IE =0;             // disable TMR1 Interrupts
                countTMR1IFs++;                 // TMR1 Flagged count number of times
                if (countTMR1IFs==10)           // Too slow for application, but it's fine for testing.
                    {
                        temp=PORTB;             // After flagging 10 times read PORTB
                        countTMR1IFs=0;         // reset counter
                    }
                PIR1bits.TMR1IF = 0;            // Reset flag
                PIE1bits.TMR1IE = 1;            // Enable TMR1 Interrupts
            }
        }
}
/**
End of File
*/
 

bug13

Joined Feb 13, 2012
2,002
Hi

It should be something like these:
Code:
void main(void){

  initial_stuff1();
  initial_stuff2();
  // initial other stuff;
  initial_timer();

  while(1){
    // main loop
  }

}

void interrupt ISR(){

  // check for timer interrupt
  if (timer interrupt flag is set){
    // clear flag
    // do stuff
  }

}
 

Thread Starter

GettinBetter

Joined Jun 22, 2018
42
Well to be honest @bug13 I thought I was..
however, I stepped through the program in debug mode and found much of what I was defining /calling in main had already been called/setup in the various MCC files.
This is how its setup now...

In main...
Code:
#include "mcc_generated_files/mcc.h"

/*
    ************* START OF MAIN ****************
*/
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();

    INTERRUPT_GlobalInterruptEnable();      // Enable the Global Interrupts
    INTERRUPT_PeripheralInterruptEnable();  // Enable the Peripheral Interrupts
   
   
   
    void TMR1_StartTimer(void);        // Start timer1 running
    while (1)
    {
           
    }
}
/**
End of File
*/
..and in the ISR ...
Code:
void TMR1_DefaultInterruptHandler(void){
  // add your TMR1 interrupt custom code
  // or set custom function using TMR1_SetInterruptHandler()
   
  unsigned char volatile temp;
  unsigned int volatile countTMR1IFs=0;
   
  countTMR1IFs++;  // TMR1 Flagged count number of times
  if (countTMR1IFs==0x0A)  // Too slow for application, but it's fine for testing.
  {
  INTCONbits.GIE = 0;  // disable global interrupts
  PIE1bits.TMR1IE =0;  // disable TMR1 Interrupts
  temp=PORTB;  // After flagging 10 times read PORTB
  __delay_ms(100);
  countTMR1IFs=0;  // reset counter
  PIR1bits.TMR1IF = 0;  // Reset flag
  PIE1bits.TMR1IE = 1;  // Enable TMR1 Interrupts
  INTCONbits.GIE = 1;
  }
}
Still not quite there though.
regards
Les
 

bug13

Joined Feb 13, 2012
2,002
have a look at this again.
  • Can't see an interrupt qualifier in your code (unless it's hidden)
  • Can't see the interrupt flag is tested (unless it's hidden)

Code:
void interrupt ISR(){
  // check for timer interrupt
  if (timer interrupt flag is set){
    // clear flag
    // do stuff
  }
}
 

nsaspook

Joined Aug 27, 2009
13,086
Well to be honest @bug13 I thought I was..
however, I stepped through the program in debug mode and found much of what I was defining /calling in main had already been called/setup in the various MCC files.
This is how its setup now...

In main...
Code:
#include "mcc_generated_files/mcc.h"

/*
    ************* START OF MAIN ****************
*/
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();

    INTERRUPT_GlobalInterruptEnable();      // Enable the Global Interrupts
    INTERRUPT_PeripheralInterruptEnable();  // Enable the Peripheral Interrupts
  
  
  
    void TMR1_StartTimer(void);        // Start timer1 running
    while (1)
    {
          
    }
}
/**
End of File
*/
..and in the ISR ...
Code:
void TMR1_DefaultInterruptHandler(void){
  // add your TMR1 interrupt custom code
  // or set custom function using TMR1_SetInterruptHandler()
  
  unsigned char volatile temp;
  unsigned int volatile countTMR1IFs=0;
  
  countTMR1IFs++;  // TMR1 Flagged count number of times
  if (countTMR1IFs==0x0A)  // Too slow for application, but it's fine for testing.
  {
  INTCONbits.GIE = 0;  // disable global interrupts
  PIE1bits.TMR1IE =0;  // disable TMR1 Interrupts
  temp=PORTB;  // After flagging 10 times read PORTB
  __delay_ms(100);
  countTMR1IFs=0;  // reset counter
  PIR1bits.TMR1IF = 0;  // Reset flag
  PIE1bits.TMR1IE = 1;  // Enable TMR1 Interrupts
  INTCONbits.GIE = 1;
  }
}
Still not quite there though.
regards
Les
Your ISR contains several no-no's. A useless 'volatile' on non-global variables inside a function (use 'static' if you wish to keep the local variable value between invocations), long delays in a ISR and diddling global interrupts inside a ISR.
 

Thread Starter

GettinBetter

Joined Jun 22, 2018
42
have a look at this again.
  • Can't see an interrupt qualifier in your code (unless it's hidden)
  • Can't see the interrupt flag is tested (unless it's hidden)

Code:
void interrupt ISR(){
  // check for timer interrupt
  if (timer interrupt flag is set){
    // clear flag
    // do stuff
  }
}
Hi @bug13 .. As the MMC puts it all in various files it's difficult to post all, but here's the points you mention I believe. I have to say, to be honest I'm not sure what "an interrupt qualifier" is.

In the interrupt_manager.c file
Code:
void INTERRUPT_InterruptManager (void)
{
  // interrupt handler
  if(INTCONbits.PEIE == 1)
  {
  if(PIE1bits.TMR1IE == 1 && PIR1bits.TMR1IF == 1)
  {
  void __interrupt() TMR1_ISR(void);
  }
  else
  {
  //Unhandled Interrupt
  }
  }
  else
  {
  //Unhandled Interrupt
  }
}
In the timer1.c file
Code:
void TMR1_ISR(void)
{

  // Clear the TMR1 interrupt flag
  PIR1bits.TMR1IF = 0;
  TMR1_WriteTimer(timer1ReloadVal);

  if(TMR1_InterruptHandler)
  {
  TMR1_InterruptHandler();
  }
}


void TMR1_SetInterruptHandler(void (* InterruptHandler)(void)){
  TMR1_InterruptHandler = InterruptHandler;
}

void TMR1_DefaultInterruptHandler(void){
  // add your TMR1 interrupt custom code
  // or set custom function using TMR1_SetInterruptHandler()

  unsigned char volatile temp;
  unsigned int volatile countTMR1IFs=0;

  countTMR1IFs++;  // TMR1 Flagged count number of times
  if (countTMR1IFs==0x0A)  // Too slow for application, but it's fine for testing.
  {
  INTCONbits.GIE = 0;  // disable global interrupts
  PIE1bits.TMR1IE =0;  // disable TMR1 Interrupts
  temp=PORTB;  // After flagging 10 times read PORTB
  __delay_ms(100);
  countTMR1IFs=0;  // reset counter
  PIR1bits.TMR1IF = 0;  // Reset flag
  PIE1bits.TMR1IE = 1;  // Enable TMR1 Interrupts
  INTCONbits.GIE = 1;
  }
}
Your ISR contains several no-no's. A useless 'volatile' on non-global variables inside a function (use 'static' if you wish to keep the local variable value between invocations), long delays in a ISR and diddling global interrupts inside a ISR.
Hi @nsaapook ..rechecked your link RE: volatile....I'll remove it....& could you be a bit more verbose about "diddling global interrupts" and I'll attend to it. i originally thought adding a delay would allow port to settle or something like that.

Incidentally guys, would it help you to assist, if I upload the project, in case somebody fancies a gander?

Regards
Les
 
Top