AnsweredAssumed Answered

Cube32MX - input capture overflow detection.

Question asked by jla on May 18, 2017
Latest reply on May 20, 2017 by jla

Hi.

 

I'm trying to use TIM1's channel 1 as a spindle RPM input capture. ( device is STM32F103C8 )
Knowing that the spindle has a single pulse per revolution and is rated from 0 to 30K rpm, the frequency domain is 0 to 500Hz. Easy feat for a timer running at 48MHz.

 

So I configured TIM1's prescaler to 480, its period to 0xFFFF, direct input, no prescaling nor filtering (sharp input signal)...
So far so good, frequencies from 5Hz to 1KHz  are registering nicely...

 

But here's my issue : I was planning to count the number of UPDATE interrupts to detemine when the signal's period dropped too much ( i.e. the spindle was idling ).

 

BUT : it seems that I'm missing some UP events. The update interrupt isn't always firing.


Here's my code. The first method is CubeMX's output.

 


/* TIM1 init function */
static void MX_TIM1_Init(void)
{

 

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_IC_InitTypeDef sConfigIC;

 

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 512;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 0xFFFF;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;    
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

 

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

 

  if (HAL_TIM_IC_Init(&htim1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

 

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

 

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

 

    
}

 

// Some global variables

volatile bool _toolRawRevValid;
volatile uint32_t _lastTim1CC,_toolRawRev, _tim1Ovf ;

 


void InitializeInputStage(void)
{
    // prepare variables 

  _toolRawRev = 0;
    _toolRawRevValid = false;
    _tim1Ovf = 0;
    _lastTim1CC = 0;
    
    // Start TIM1 and its interrupts (as configured in MX_TIM1_Init() ).
    HAL_TIM_Base_Start_IT(&htim1); // start counting, enable UPDATE interrupt
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // enable IC interrupt (already counting now).
}

 

// Auto-reload (update) event interrupt handler

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim1)
    {
        _tim1Ovf++; // count roll-overs.
        if(_tim1Ovf >= 2)
            _toolRawRevValid = false;
    }
}

 

// Timers Capture handler

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    register uint32_t currCap, ovf, tc;
    
    if(htim == &htim1){
        currCap = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);
        tc = TIM1->CNT;
        ovf    = _tim1Ovf; // number of TIM1-CNT rollovers
        _tim1Ovf = 0;
        
        if(currCap <= _lastTim1CC) {
            if(!ovf){ // no roll-over occured ?
                while(1)
                    __NOP; // the previously captured value is higher than the current one, but no timer overflow registered ?
            }
            _toolRawRev = ((TIM1->ARR * ovf) + currCap )-_lastTim1CC;
        }else{
        _toolRawRev = (TIM1->ARR * ovf) + (currCap - _lastTim1CC);
        }
        _toolRawRevValid = true;
        
        _lastTim1CC = currCap;
        }
    
}

 

 

 

 

So here's the strange fact : my program keeps hitting the __NOP statement in the HAL_TIM_IC_CaptureCallback(...) method.
Is Timer1 gated by its input capture somehow ?

 

 

PS: sorry for the repetitive edits, I'm discovering the community's new interface. =/

Outcomes