MC9S08GT60 Timer interrupt modulo problem...

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC9S08GT60 Timer interrupt modulo problem...

5,146 Views
Danny
Contributor I
I am currently developing software for the MC9S08GT60 and i am trying to implement timer interrupts. I am using TPM1. i have set CPWMS to 0 which enables the counter as a simple up counter and i have enabled TOIE. i have my code entering the interrupt service routine (vector location 8) upon timer oferflow from 0xffff to 0x0000 but i cannot manage to get it to overflow on my software determined modulo value... in my understanding it is a simple procedure of writing to the modulo value registers (TPM1MODL and TPM1MODL ) to enable the modulo overflow interrupt. (i.e. interrupt and reset to 0x00 after my count value rather than the overflow from 0xff to 0x00) I am ovoiding using the Channels because it seems overcomplicated for my application especially when im sure its possible to trigger the int on modulo overflow!
 
i have included the basics of the code i am using. please feel free to scrutanise  as i would love to know a solution. obviously there are fragments of code missing but the register set up should be as shown
 
my intentions are this:
*enable external interrupts on PORTA bit 7
*enable internal timer interrupts with a modulo value
*change the modulo value dependant on variable (set elsewhere) and the externally generated interrupt
 
*do stuff when the timer reaches that modlo value (which is a certain time after the external interrupt decided by the variable)
*return to normal code and wait for the next external interrupt
 
 
PLEASE HELP ME ENABLE THE MODULO OVERFLOW INTERRUPT instead of interrupting after 0xffff
 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <hidef.h>        /* for EnableInterrupts macro */
#include <MC9S08GT60.h>   /* include peripheral declarations */
#include <Demo_1.h>
#include <UART.h>         /* include UART initialisation*/

#define PRESCALER 0
 
int i = 0;
int value = 0;
int flag = 0;

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

interrupt EXTERNAL_INT void ext_int()
{

DisableInterrupts;                // disable interrupts
   
    // EXTERNAL KEYBOARD INTERRUPT DETECTED 
      
  TPM1CNT = 0x00;      // reset timer to zero (any write to TPM1CNT does this)
   
    TPM1MOD = 0xffff; // write modulo value
    
  TPM1SC_TOIE = 1;             // timer interupt on overflow enabled
EnableInterrupts;               // enable interrupts
 KBI1SC_KBACK = 1;               // acknowlege interrupt
 
}                                 // RTI

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
interrupt INTERNAL_TMR_INT void TMR1_int()
{
 
// DO STUFF HERE when modulo expires
   
  TPM1SC_TOF = 0;               // clear timer overflow flag
  TPM1SC_TOIE = 0;              // timer interupt overflow disabled
   }
}                                 // RTI
 
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

void main(void) {
 
SOPT_COPE = 0;                    // disable watchdog

/* PORT A DATA DIRECTION */

PTADD_PTADD7 = 0;         // initalise bit 7 of port A as input 
PTAPE = 0xff;                      // enable pullups on PORTA      
 
/* ENABLE PORTA KEYBOARD INTERRUPT */
KBI1PE_KBI1PE7 = 1;             // enable portA pin 7 as input with keyboard int
KBI1SC_KBI1E = 1;         // enable keyboard interrupts

 
/*Initalise timer TPM1 channel, asssume not touched since reset*/
TPM1SC_CLKSA = 1;                 // select bus clock (4MHz)  (B:A = 0:1)
TPM1SC_CLKSB = 0;
TPM1SC_CPWMS = 0;                 // 16bit counter is set to count up from 0x00 ot 0xff or to modulo  (i.e. PWM disabled)
 
TPM1SC_TOIE = 1;                  // timer interupt on overflow enabled
TPM1SC_PS = PRESCALER;      // set clock divider 4Mhz when 0
 
EnableInterrupts;                 // enable interrupts
 
 
 for(;:smileywink:
 {
    
  /* loop forever */
 }
}
 
 
 
 
 
 
Labels (1)
0 Kudos
4 Replies

379 Views
rhinoceroshead
Contributor I
Yes, it should interrupt on the modulo value that you set.  I see a couple things wrong with your code, though.
 
1)  In your KBI service routine, you are re-enabling interrupts before you are clearing the KBI flag - which should make the pending interrupt happen over and over again.  I think this should be making your stack overflow.  Is it?  I always clear the flag right away at the beginning of the ISR.  Also, you do not need to disable interrupts at the beginning of an ISR because the CPU does that for you.  And in this case, since you are re-enabling them at the end of your ISR, there is no point in doing it at all since the CPU will restore the I bit in the CCR register back to the state it was in before the ISR occurred.  The only time you should enable interrupts in an ISR is if you want that ISR to be interruptable.
 
2)  Even though it looks like it, you are not actually clearing the overflow flag in your overflow interrupt routine.  If you check the data sheet, the flag clearing procedure needs to have a read of the TPM1SC register before writing a 0 to the TOF.  Check the data sheet, page 161.  (You also have an extra curly brace at the end, but that was probably just a typo.)
 
So, I recommend this:
 
interrupt EXTERNAL_INT void ext_int()
{
    // EXTERNAL KEYBOARD INTERRUPT DETECTED 
 KBI1SC_KBACK = 1;               // acknowlege interrupt
 TPM1CNT = 0x00;      // reset timer to zero (any write to TPM1CNT does this)
 TPM1MOD = 0xffff; // write modulo value
 TPM1SC_TOIE = 1;             // timer interupt on overflow enabled
}                                 // RTI
 
and this:
 
interrupt INTERNAL_TMR_INT void TMR1_int()
{
 char temp;
 temp = TPM1SC;                  // read timer status and control
  TPM1SC_TOF = 0;               // clear timer overflow flag
  TPM1SC_TOIE = 0;              // timer interupt overflow disabled
 // DO STUFF HERE when modulo expires
}                                 // RTI
 
or this:
 
interrupt INTERNAL_TMR_INT void TMR1_int()
{
 TPM1SC &= ~0x80;              // read timer status and clear flag
  TPM1SC_TOIE = 0;              // timer interupt overflow disabled
// DO STUFF HERE when modulo expires
}
0 Kudos

379 Views
rhinoceroshead
Contributor I
One other thing.  Just because you are disabling the timer overflow interrupts from time to time doesn't mean that the flags stop coming.  If there is enough time between a disabling and enabling of the timer overflow interrupt for the mod to be reached on the timer, a flag will appear, and when you re-enable the interrupt, it will immediately start running the overflow ISR, since a flag is already there.  You should ensure that the overflow flag is clear before enabling the overflow interrupt.
0 Kudos

379 Views
Danny
Contributor I
WOW! that was the quickest reply that i have ever recieved!! thankyou so much! i will make the changes immediatly and let you know!
 
 
cheers once again!
beers all round if it works!
 
 
0 Kudos

379 Views
Danny
Contributor I
EVERYTHING WORKS BEAUTIFULLY!!!!!!

thanx for the advice!!
0 Kudos