Search code examples
ctimerstm32stm32f7

STM32F7 Timer triggers Timer


I generated some code with CubeMX. I want that timer 2 is triggering timer 3. If an overflow on Timer 2 occurs, Timer 3 should count up 1. I tried some configurations but nothing worked - no interrupt on timer3 when I set the output trigger (timer 2)

sMasterConfig.MasterOutputTrigger

to the same value as (timer 3)

sSlaveConfig.SlaveMode

I have still no interrupt on timer 3

This is the full configurationcode from both Timers:

TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;

/* TIM2 init function */
void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 54;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 250;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

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

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 8000;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

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

Solution

  • Config structs should be initialized.

    void MX_TIM2_Init(void)
        {
          TIM_ClockConfigTypeDef sClockSourceConfig;
    

    Structures defined in a function body will not be initialized, fields not explicitly initialized will get some unpredictable value.

          TIM_ClockConfigTypeDef sClockSourceConfig = {};
    

    Using this form will explicitly zero all fields before use.

    Wrong input trigger

    sSlaveConfig.InputTrigger = TIM_TS_ITR0;
    

    Using ITR0 makes TIM3 a slave of TIM1. The correct value is TIM_TS_ITR1. See the TIMx internal trigger connection table at the end of the desciption of the TIMx slave mode control register TIMx_SMCR in the Reference Manual.

    A working example without HAL

    Well, it's still using a few useful macros from HAL.

    void TIM3_IRQHandler(void) {
        if(TIM3->SR & TIM_SR_UIF) {
            TIM3->SR = ~TIM_SR_UIF;
            do_something();
        }
    }
    
    void starttimers(void) {
        NVIC_EnableIRQ(TIM3_IRQn);
        __HAL_RCC_TIM2_CLK_ENABLE();
        __HAL_RCC_TIM3_CLK_ENABLE();
    
        TIM3->ARR = 8000;               // slave timer period
        // trigger selection TS=001 ITR1 = TIM2, slave mode SMS=0111 external clock mode 1
        TIM3->SMCR = TIM_TS_ITR1 | TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_2;
        TIM3->DIER = TIM_DIER_UIE;      // interrupt on update event (timer overflow)
        TIM3->CR1 = TIM_CR1_CEN;        // enable timer 3
    
        TIM2->PSC = 54;                 // prescaler preload
        TIM2->EGR = TIM_EGR_UG;         // update prescaler
        TIM2->ARR = 250;                // master timer period
        TIM2->CR2 = TIM_TRGO_UPDATE;    // master mode selection MMS=010 Update event
        TIM2->CR1 = TIM_CR1_CEN;        // enable timer 2
    }