AnsweredAssumed Answered

Timer4 CCP2 Interrupt occur too early (about 70% of the time)

Question asked by slimsly on Jul 25, 2013
Latest reply on Jul 26, 2013 by slimsly
Hello,

I have a problem with STM32F103RB Timer4 Compare Module.The Timer 4 Compare2 match interrupt trigger indiscriminately.When view with a logic analyzer, I found out that the interrupt occurs too early most of the time and  rarely at the right time.

//Timer 4 Configuration
void TIM4_Configuration(void)
 {
    
    TIM4->PSC = (20 - 1);
    TIM4->ARR = 0xFFFF;                          //TIM4 Auto Reload Value Set to 10us*/
    TIM4->EGR = TIM_EGR_UG;                          //Reload Prescaler and Other Registers*/
    TIM4->CR1 = TIM_CR1_CEN;                     //Start TIM4
    NVIC_EnableIRQ(TIM4_IRQn);                   //Enable Timer4 Interrupt in NVIC    
 }
 
This routine below is in ADC Interrupt Handler.I setup a dummy timer(test purpose). A zero crossing is detected once the time 0.6ms expire.I use Timer4 Counter to measure the period.I load the measured period into  Timer 4 compare2 register and enable Timer4 CCP2 interrupt.

The problem is the Interrupt occurs too early (70% of the time , I did a long capture with Logic analyzer) and not at the 0.6ms I was expecting. if I replace "CommuationTime" in the below code with 0.6ms equivalent constant (2159) value, the interrupt occurs at the exact 0.6ms period.

I thought that Timer4 counter is not counting properly so I setup ITM Debug (printf) Viewer to see the value of "CommuationTime" during runtime.it reported  a value close to 2159 so do the value when view in STM Studio during runtime.

If "CommuationTime" value is right which means the Timer4 counter is incrementing properly, why is it that the Timer4 CCP2 interrupt trigger too early when I assign "CommuationTime" to Timer4 CCP2 Register but trigger at the right time when I assign it equivalent constant value?.

I notice that "FilterCommuationTime = TIM4->CNT;" in TIM4_IRQHandler report a very low value (less than 100) instead of a value sligntly above 2159 (plus code execution time, interrupt latency).

//This code is in ADC Interrupt Handler
------------------------------------------------------
         if (ZeroCrossing == Detected)
                 {        
                    
                    GPIOB->ODR ^= (1 << 8);
          GPIOB->BSRR = (1 << 9);    
                    
                    TIM4->CR1 &= ~TIM_CR1_CEN;                        //Stop TIM3
                    CommuationTime = TIM4->CNT;                       //Retrieve the Zero Crossing Period    
                    TIM4->CCR2 = CommuationTime;                //Load Tim4 CC2 with the Next Commutation Period
                    //Works when I replace TIM4->CCR2 = 2159
            TIM4->EGR = TIM_EGR_UG;                          //Reload Prescaler and Other Registers*/    
                    TIM4->CNT = 0;                                       //Reset Timer4 Counter                    
                    TIM4->DIER = TIM_DIER_CC2IE;                      //Enable Tim4 CC1 Interrupt
                    
                    TIM2->DIER &= ~TIM_DIER_CC1IE;                              //Disable Tim2 CC1 Interrupt (2nd ADC Sample Point)        
                    TIM1->DIER &= ~TIM_DIER_CC4IE;                              //Disable Tim1 CC4 Interrupt (1st ADC Sample Point)    
                    NVIC_ClearPendingIRQ(TIM2_IRQn);    
                    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);            
            
                 }
---------------------------------------------
void TIM4_IRQHandler(void)
    {
        
    if (TIM4->SR & TIM_SR_CC2IF)
        {
       GPIOB->BRR = (1 << 9);                
         TIM4->SR &= ~TIM_SR_CC1IF;                   //Clear Timer3 CC1 Interrupt Flag
     FilterCommuationTime = TIM4->CNT;            
         TIM4->CNT = 0;                                 //Reset Timer4 Counter
        
         Commutate();                                 //Preload Next Commutation pattern
            
         TIM3->DIER = TIM_DIER_CC1IE;                            //Enable Timer3 CC1 Interrupt    
         TIM3->CNT = 0;                                   //Reload Prescaler and Other Registers
       TIM3->CR1 = TIM_CR1_CEN;                     //Start TIM3    
             
         TIM4->DIER &= ~TIM_DIER_CC1IE;                     //Disable Tim3 CC1 Interrupt
       GPIOB->BRR = (1 << 9);    
     }
}
------------------------------------


I can't understand what is going on.I have tried all "abracadabra" known to me but it just don't do it.
I need help..

Thanks
Sylvester

Outcomes