2020-03-04 11:05 AM
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 ?
2020-03-04 11:17 AM
Did you try to set the counter periode in your setup_timer function?
Also Check timer interrupt in CubeMX and pre-load
2020-03-04 11:30 AM
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.
2020-03-05 07:53 AM
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 */
}
}
2020-03-06 10:58 AM
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.
2020-03-08 07:01 PM
can I ask how to do it with STM32L4R9ZI? and how to find it on the reference manual on what part?
2020-03-08 10:30 PM
In the RCC register descriptions chapter, find the bit which enables the timer in your MCU.
In the NVIC chapter, find out how the timer update interrupt is actually called, if TIM2_IRQn gives a compile error.