Skip to main content
VChav.19
Associate II
March 4, 2020
Question

Cant Setup Timer Interrupt with HAL and STM32CubeMX.

  • March 4, 2020
  • 2 replies
  • 1994 views

Im using an STM32L452RE dev. board. and Im trying to set an interrupt once after some time. I have the following subroutines.

#define MICROSECOND_TICK_COUNT 80 //clock = 80 MHZ i.e. 1e-6/(1/80e6)=80
TIM_HandleTypeDef myTimer;
 
void setupTimer(void){
	TIM_ClockConfigTypeDef sClockSourceConfig = {0};
	TIM_MasterConfigTypeDef sMasterConfig = {0};
	myTimer.Instance = TIM2;
	myTimer.Init.Prescaler =0;
	myTimer.Init.CounterMode = TIM_COUNTERMODE_UP;
	myTimer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	myTimer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	myTimer.Init.Period = 0;
	HAL_TIM_Base_Init(&myTimer);
	sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
	HAL_TIM_ConfigClockSource(&myTimer, &sClockSourceConfig)
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	HAL_TIMEx_MasterConfigSynchronization(&myTimer, &sMasterConfig) != HAL_OK
}
 
void startTimer(uint32_t microseconds){
	myTimer.Init.Period = microseconds*MICROSECOND_TICK_COUNT;
	HAL_TIM_Base_Init(&myTimer)
	HAL_TIM_Base_Start_IT(&myTimer);
}
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance==myTimer.Instance){
		stopTimer2();
	}
}

The interrupt is generated but the timing is incorrect. I checked with a scope and independently of the values I set for Period, Prescaler and ClockDivision from the HAL struct "TIM_HandleTypeDef " in my subroutines I always get the interrupt at a same time. . Is there anything else Im missing ?

This topic has been closed for replies.

2 replies

GIkar
Associate III
March 4, 2020

Did you try to set the counter periode in your setup_timer function?

Also Check timer interrupt in CubeMX and pre-load

VChav.19
VChav.19Author
Associate II
March 4, 2020

Yes, I set the period on Line 12 (setupTimer). Its set to zero since I modify the period with the startTimer function. Likewise I activated the interrupt on CubeMX.

Also the auto-preload option is disabled.

berendi
Principal
March 5, 2020

I too couldn't figure it out in HAL. Just use the register interface, as documented in the reference manual.

void setupTimer(void) {
	RCC->APB1ENR1 = RCC_APB1ENR1_TIM2EN; // enable TIM2 clock
	RCC->APB1ENR1; // wait a bit
	TIM2->DIER = TIM_DIER_UIE; // enable interrupt in timer
	NVIC_EnableIRQ(TIM2_IRQn); // enable TIM2 interrupt in NVIC
}
 
void startTimer(uint32_t microseconds){
	TIM2->ARR = microseconds * MICROSECOND_TICK_COUNT; // set timer period
	TIM2->CR1 = TIM_CR1_CEN | TIM_CR1_OPM; // start TIM2 in one pulse mode
}
 
void TIM2_IRQHandler(void) {
	uint32_t sr = TIM2->SR;
	TIM2->SR = ~sr; // clear timer status
	if(sr & TIM_SR_UIF) {
		/* period elapsed */
	}
}

VChav.19
VChav.19Author
Associate II
March 6, 2020

Thanks, Thats what I did at the end. I just had a look on how the HAL layer works and for my application I considered easier to work with the registers. The problem with the HAL is that it modifies the EGR register for updating the prescaler .... which updates the SR flag and when calling the interrupt I get the interupt for the EGR update and afterwards the timings are correct.