MC9S08DZ16 Timer Overflow interrupt

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

MC9S08DZ16 Timer Overflow interrupt

794件の閲覧回数
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.

タグ(4)
0 件の賞賛
2 返答(返信)

524件の閲覧回数
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 件の賞賛

524件の閲覧回数
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 件の賞賛