cancel
Showing results for 
Search instead for 
Did you mean: 

Input capture interrupts ignored

fabio239955_st
Associate II
Posted on June 29, 2017 at 18:22

I'm using stm32f767NI.

I need to use a timer in input capture mode, but I would like to adapt the prescaler to the input frequency.

So I set the same channel of the timer in TimeBase mode to catch overflows and in Input Capture mode to have frequency estimation. If I have more than two overflows, I calcule the prescaler on the numbers of overflows.

I fix the input frequency on 15kHz and I have 14400 counts between two rising edges of the signal, but sometimes I have 28800 counts. Sometimes one capture interrupt is ignored.

These are the two interrupt routines:

Overflows interrupt routine:

    __HAL_TIM_CLEAR_IT(&(timDrvInst[TIM8_INST].timInst), TIM_IT_UPDATE);    

     timDrvInst[TIM8_INST].ICOverflows++;

Input Capture interrupt routine:

     __HAL_TIM_CLEAR_IT(&(timDrvInst[TIM8_INST].timInst), TIM_IT_CC3);

     timDrvInst[TIM8_INST].timInst.Channel = HAL_TIM_ACTIVE_CHANNEL_3;

    HAL_TIM_IC_CaptureCallback(&(timDrvInst[TIM8_INST].timInst));

    timDrvInst[TIM8_INST].timInst.Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;

Initialization of the timer:

    TIM_IC_InitTypeDef     sICConfig;

  /* Set TIMx instance */

  timDrvInst[*instInd].timInst.Instance = tim;

  /* Initialize TIMx peripheral as follows:

       + Period = 0xFFFF

       + Prescaler = 0

       + ClockDivision = 0

       + Counter direction = Up

  */

  timDrvInst[*instInd].timInst.Init.Period            = 0xFFFF;

  timDrvInst[*instInd].timInst.Init.Prescaler         = 0;

  timDrvInst[*instInd].timInst.Init.ClockDivision     = 0;

  timDrvInst[*instInd].timInst.Init.CounterMode       = TIM_COUNTERMODE_UP;

  timDrvInst[*instInd].timInst.Init.RepetitionCounter = 0;

    

    if (HAL_TIM_Base_Init(&(timDrvInst[*instInd].timInst)) != HAL_OK)

  {

    /* Initialization Error */

    return RET_TIM_INIT_ERROR;

  }

  /*##-2- Start the TIM Base generation in interrupt mode ####################*/

  /* Start Channel1 */

  if (HAL_TIM_Base_Start_IT(&(timDrvInst[*instInd].timInst)) != HAL_OK)

  {

    /* Starting Error */

    return RET_TIM_INIT_ERROR;

  }

  HAL_TIM_IC_MspInit(&(timDrvInst[*instInd].timInst));

  sICConfig.ICPolarity  = TIM_ICPOLARITY_RISING;

  sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;

  sICConfig.ICPrescaler = TIM_ICPSC_DIV1;

  sICConfig.ICFilter    = 0;

    //Inizializzo meanDiv, cioè il il numero di ingressi per calcolare un perdiodo medio

    timDrvInst[*instInd].meanDiv = 1;

  if(HAL_TIM_IC_ConfigChannel(&(timDrvInst[*instInd].timInst), &sICConfig, chan) != HAL_OK)

  {

    /* Configuration Error */

    return RET_TIM_INIT_ERROR;

  }

  /*##-3- Start the Input Capture in interrupt mode ##########################*/

  if(HAL_TIM_IC_Start_IT(&(timDrvInst[*instInd].timInst), chan) != HAL_OK)

  {

    /* Starting Error */

    return RET_TIM_INIT_ERROR;

  }  

void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim) 

{

        GPIO_InitTypeDef   GPIO_InitStruct;

            /* Configure  (TIMx_Channel) in Alternate function, push-pull and high speed */

        GPIO_InitStruct.Pin = GPIO_PIN_7;

        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

        GPIO_InitStruct.Pull = GPIO_PULLUP;

        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

        GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;

        HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

        /* Enable GPIO channels Clock */

        __HAL_RCC_GPIOI_CLK_ENABLE();

        __HAL_RCC_TIM8_CLK_ENABLE();

        HAL_NVIC_SetPriority(TIM8_CC_IRQn, 3, 0);

        /* Enable the TIMx global Interrupt */

        HAL_NVIC_EnableIRQ(TIM8_CC_IRQn);    

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)

{

        __HAL_RCC_GPIOI_CLK_ENABLE();

        __HAL_RCC_TIM8_CLK_ENABLE();        

        HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 4, 1);

        /* Enable the TIMx global Interrupt */

        HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);

}

What is wrong?

5 REPLIES 5
Posted on June 29, 2017 at 21:54

Just an observation, but

 __HAL_RCC_GPIOI_CLK_ENABLE(); // Do this BEFORE using 

 HAL_GPIO_Init()

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Zt Liu
Senior III
Posted on June 30, 2017 at 03:45

I'm not familiar with F7, but firstly, as Clive One pointed out, you need to Enable clock before writing the registers.

Secondly, if you are using HAL library,

you have to check is it acceptable to start the handle twice in different modes.

(exam the library you will see lots of handle status check)

What is the frequency range of your signal? what resolution you need?

Do you just need to measure the frequency or even duty?

fabio239955_st
Associate II
Posted on June 30, 2017 at 09:16

In the hal library there is a flag that avoid to configure IC mode and Time Base mode simultaneously:

if I used HAL_TIM_IC_Init instead of HAL_TIM_IC_MspInit, the state of the timer would be CONFIGURED, set by HAL_TIM_Base_Init.

I bypass this control calling HAL_TIM_IC_MspInit and the timer works well almost anytime but one in a dozen of capture event.

My signal frequency can be between 100mHz and 20Khz

I just need to measure frequency.

Zt Liu
Senior III
Posted on July 01, 2017 at 13:54

Don't have F7 at hands right now.

I found that  F767 has 32 bit timer like TIM2 or you can chain two 16 bit timers to get a 32 bit timer to cover 

timer counts from 10800(20KHz) to 2160000000(100mHz). Using the later model, you can actually count overflows in your scenario.

fabio239955_st
Associate II
Posted on July 03, 2017 at 12:26

SOLVED:

Reading the compare register of the timer in the overflow routine cause an access problem with capture hardware.

The capture value is not saved, so when the overflow routine ends and the capture routine starts, the capture value is lost. I have the value of the last capture and not of the actual.

Could be the same problem if I loose an overflow: when I update the prescaler, I need to write update event, then I restart the compare. Could this cause some problems to the timer overflow interrupt? What is the right routine to update prescaler?