cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Timer Output compare

SS.Sagar
Associate III

I am using STM32L476 Nucleo board and cubemx. I want to use Output compare channel 1 for timeout of 2ms. i have configure the timer but timer is not giving interrupt for Output compare. i am getting interrupt for period i gives for timer. but not for output compare. Here is my timer configuration.

static void MX_TIM1_Init(void)
{
 
  /* USER CODE BEGIN TIM1_Init 0 */
 
  /* USER CODE END TIM1_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
  /* USER CODE BEGIN TIM1_Init 1 */
 
  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = TIMER1_PRESCALER_VAL;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = TIMER_PERIOD;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
  sConfigOC.Pulse = 1000 * TIMER_OC_1_VAL;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */
  HAL_TIM_OC_Start_IT(&htim1,TIM_IT_CC1);
 
  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);
 
}

i tried changing the sConfigOC.Pulse value but i don't see expected behavior.

2 REPLIES 2
turboscrew
Senior III

Did you write the interrupt handler with the correct name?

That is:

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)

And the obvious: The TIMER_PERIOD is longer than 1000 * TIMER_OC_1_VAL?

berendi
Principal

The timer configuration in CubeMX and HAL is quite poorly documented. The generated code has lots of unnecessary diversions.

Use the register interface, which is documented in detail in the reference manual.

// interrupt handler for TIM1 capture/compare event
void TIM1_CC_IRQHandler(void) {
	uint32_t sr = TIM1->SR; // read interrupt flags
	TIM1->SR = ~sr; // clear interrupt flags before proceeding
	if(sr & TIM_SR_CC1IF) {
		// capture event
	}
}
 
void TIM1_UP_TIM16_IRQHandler(void) {
	uint32_t sr = TIM1->SR; // read interrupt flags
	TIM1->SR = ~sr; // clear interrupt flags before proceeding
	if(sr & TIM_SR_UIF) {
		// update event
	}
}
 
int main(void) {
	RCC->APB2ENR = RCC_APB2ENR_TIM1EN; // enable timer clock in RCC
	RCC->APB2ENR;
	TIM1->PSC = 80 - 1; // just as example, use a prescaler to get a 1 us base clock
	TIM1->EGR = TIM_EGR_UG; // update event to write prescaler shadow register
	TIM1->SR = 0; // clear interrupt flasg set by the update event
	TIM1->ARR = 10000 - 1; // must be > CCR1
	TIM1->CCR1 = 2000 - 1; // 2 ms
	TIM1->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE; // enable CC and update interrupts in timer
	TIM1->CR1 = TIM_CR1_CEN; // start timer
	NVIC_EnableIRQ(TIM1_CC_IRQn); // enable CC interrupt in NVIC
	NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); // enable update interrupt in NVIC
	while(1)
		;
}

Consult the timer register descriptions and the timer functional description in the reference manual.