AnsweredAssumed Answered

Timer1 reset on trigger

Question asked by de_craemer.klaas on Jul 7, 2012
Latest reply on Jul 9, 2012 by de_craemer.klaas
I found something very funny/weird when using TIM1 to measure the frequency of a signal:

Set TIM2 and TIM1 to use the same prescaler (e.g. 8). TIM2 is configured to generate PWM with period 10000, in this case resulting in 2Mhz/(8*10000)=25Hz signal.

Then, TIM1 is configured in Input CapCom mode, and its trigger controller resets the timer on every rising edge on input channel1.
Now connect pins TIM2_Chan1 with TIM1_Chan1. In theory, the values obtained in CapCompareReg1 of TIM1 should equal the period of TIM2 perfectly.

In this example, the CCR1 contains 8880 instead of 9999. The values deviate even more worse when taking smaller prescalers for TIM1.

-------------------
Main code
:
    TIM1_DeInit();
    /* Set TIM1 Frequency to 1 Mhz (=2Mhz/2), thus 1 unit = 1us */
  TIM1_TimeBaseInit(8, TIM1_COUNTERMODE_UP, 60000, 0);//Max 60000 steps before overflow
    

  /* TIM1 channel 1 is used (PC1) with rising edge and no divider (1) nor filter (0) */
  TIM1_ICInit(TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI,  TIM1_ICPSC_DIV1, 0x00);    

  /* the trigger input (TRGI) to used to synchronize the counter */
    TIM1_SelectInputTrigger(TIM1_TS_TI1FP1);
  /* Reset mode - Rising edge of the selected trigger signal (TI1FP1 in this case) re-initializes the counter and
     generates an update of the registers. */
  TIM1_SelectSlaveMode(TIM1_SLAVEMODE_RESET);
  /* Overflow interrupt ; Capture1 interrupt enabled */
  TIM1_ITConfig(TIM1_IT_UPDATE | TIM1_IT_CC1, ENABLE);
  /* Generate an update event */
  TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);
  /* Clear CC1 and update Flag */
  TIM1_ClearFlag(TIM1_FLAG_CC1 | TIM1_FLAG_UPDATE);
    //Update URS bit van TIM_CR1 so only over/underflow generates interrupt.
    TIM1_UpdateRequestConfig(TIM1_UPDATESOURCE_REGULAR);
    /* Enable TIM1 */
  TIM1_Cmd(ENABLE);
    TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);

    //---------------------------
    TIM2_TimeBaseInit(TIM2_PRESCALER_8, 9999);
    /* PWM1 Mode configuration: Channel1 */
    TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 4000, TIM2_OCPOLARITY_HIGH);
    TIM2_OC1PreloadConfig(ENABLE);
    TIM2_ARRPreloadConfig(ENABLE);
    /* TIM2 enable counter */
    TIM2_Cmd(ENABLE);
    //---------------------------


  /* Enable general interrupts */
  enableInterrupts();


-----------------------------------
Interrupt handler for TIM1 CapCom:

void TIM1_CAP_COM_IRQHandler(void) interrupt 12
{
    measuredTime = (TIM1_GetCapture1());
    TIM1_ClearFlag(TIM1_FLAG_CC1);//Clear capture-compare flag
}


So, the timer must lose "counts" somewhere. Ironically, it is more accurate to do the whole thing with EXTI interrupts and start/stop the counter in software.
I would love to believe that my code is wrong, but it dawns on me that the while timer synchronisation implementation could be a piece of crap.

Outcomes