MC9S08DZ16 Timer Overflow interrupt

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

MC9S08DZ16 Timer Overflow interrupt

766 Views
ecorini
Contributor I

Hello, 

I'm using S08DZ16 microcontroller, and i'm trying to use timer overflow interrupt to get time a measuring function.

I've problems to get the correct number of overflows.

Timer initialization:

#define TPM1_MOD_VALUE (1000U) ///< TPM1 Module value used to get 1ms period.

// Module Counter @1MHz, Period value 1ms

/* TPM1SC: TOF=0,TOIE=0,CPWMS=0,CLKSB=0,CLKSA=0,PS2=0,PS1=0,PS0=0 */
TPM1SC = 0x00; // Stop and reset counter
TPM1MOD = TPM1_MOD_VALUE ; // Period value setting
(void)(TPM1SC == 0); // Overflow int. flag clearing (first part)
/* TPM1SC: TOF=0,TOIE=1,CPWMS=0,CLKSB=0,CLKSA=1,PS2=0,PS1=1,PS0=1 */
TPM1SC = 0x4B; // Int. flag clearing (2nd part) and timer control register setting

Timer start function:

void ResetTimer( void )
{
   m_TPM1OFCtr = 0;
   m_StartTimer = TPM1CNT;
}

Timer get function:

UINT GetTimer( void )
{
   return (m_TPM1OFCtr * TPM1_MOD_VALUE + TPM1CNT - m_StartTimer);
}

IRQ for timer overflow:

INTERRUPT TPM1Overflow( void )
{
   (void) TPM1SC;
   TPM1SC_TOF = 0;
   //Increment overflow counter
   m_TPM1OFCtr++;
}

In particular sometimes happens that the number of overflow is 1 less or 1 more than expected.

Tags (4)
0 Kudos
2 Replies

496 Views
kef2
Senior Contributor IV

Hi,

The problem is you need some synchronization between overflow ISR and reading TPM1CNT.

There is nice old HC11 reference manual, which explains how to "sync" your time measurements with timer overflow, with few asm examples http://www.nxp.com/docs/en/reference-manual/M68HC11RM.pdf

Didn't verify it, but you need something like this

UINT GetTimer( void )
{
UINT tcnt;
UINT ovcnt;
  
 __asm("SEI");
 tcnt = TPM1CNT; // capture CNT once!

 ovcnt = m_TPM1OFCtr;

 // increment ovcnt if 1) TOF is set and
 // 2) sampled TPM1CNT was closer to previous overflow than to next overflow
 if( TPM1SC_TOF && (tcnt < TPM1_MOD_VALUE / 2u))
  ovcnt ++;
  

 __asm("CLI");

    return (ovcnt * TPM1_MOD_VALUE + tcnt - m_StartTimer);
}

void ResetTimer( void )
{
 __asm("SEI");
 m_TPM1OFCtr = 0;
 m_StartTimer = TPM1CNT;

 // decrement ovcnt if 1) TOF is set and
 // 2) sampled TPM1CNT was closer to previous overflow than to next overflow
 if( TPM1SC_TOF && m_StartTimer < TPM1_MOD_VALUE / 2u)) // (m_StartTimer should be unsigned)
  m_TPM1OFCtr --;
 
 __asm("CLI");
}

Unless TPM1 is used for PWM, you should keep TPM_MOD_VALUE at its max, lowering interrupt rate. For timer duration <= 2 ^ 16 you wouldn't need timer overflow at all. For longer durations you need to switch to wider integer than UINT anyway

Regarding if(m_StartTimer < TPM1_MOD_VALUE / 2u)  16 bit compare. For mod value /2 = 500, you can test against close value 2 ^ 9 = 512.   if( (m_StartTimer & 512) == 0 ) may be faster, at least with some compiler switches

Regards

Edward

0 Kudos

496 Views
ecorini
Contributor I

As you said i have to block TPM_MOD_VALUE to use TPM1 for PWM.

Thanky you for your response. timer overflow "sync" works.

 

0 Kudos