cancel
Showing results for 
Search instead for 
Did you mean: 

Timer cycle duration is always the same

nogema
Associate II

Hello,

My firmware sends data to TTN when I double push on the button of my board. When the first push is detected, the board wakes up from low power mode and a timer is launched to detect if there is a second push. At the end of the countdown, if there was another push, the board sends data. Then, the counter of pushs variable is reset and the board goes in low power mode.

I configured the Timer2 in order that it makes cycles of 500 ms :

  •    clock source : internal clock (48 MHz)
  •    prescaler : 1000
  •    counter period : 24000
  •    auto-reload preload
  •    so time interval is : (1 000 * 24 000) / 48 000 000 Hz = 0.5 seconds

 My problem is no matter what the value of counter period x prescaler (I tried with 12 000 000, 24 000 000, 4 800 000, 48 000 000), the timer counts cycles of 1min30 (I toggle a LED when a new cycle begins).

Do you have any idea what I did wrong or miss in my firmware ? I can add the source code if needed.

I am using a custom board with the LoRa E5 STM32WL5EJC module embedded, the STM32WL package and the LoRaWAN middleware enabled.

Thanks you in advance

Regards

1 ACCEPTED SOLUTION

Accepted Solutions
nogema
Associate II

PROBLEM SOLVED :

I removed MX_LoRaWAN_Init() and MX_LoRaWAN_Process() functions in the main loop, then the timer TIM2 ran correctly. When I added again those functions, the timer had bad cycles. So the problem came from the LoRaWAN middleware. Then I remembered I already used a timer to send periodicaly data. To do that, I used the utilities timer with UTIL_TIMER functions.

So I disabled the timer TIM2, I created another timer with the UTIL_TIMER functions for my button and a callback function and it worked.

Thank you for your help

View solution in original post

6 REPLIES 6
gbm
Lead III

Since we are engineers, not witches, we have no idea on anything related to the code we cannot see.

Bob S
Principal

Are you using HAL functions to configure the timer or your own code? As @gbm​ suggested, show us your (relevant) code.

> auto-reload preload

With auto-preload enabled, you can't just write to the ARR register (are ARE writing to the ARR register, correct?), you also need to trigger an update to make that new value "active". The HAL library code should do that for you.

Values for prescaler and count are N-1, being as it's using a HW comparator

Expect it to walk-off over time if you've got the frequency wrong, and divergent.

The prescaler is always 16-bit, depending on the TIM the count might be 16 or 32-bit when it wraps.

If you're counting ~500ms periods this shouldn't be an issue. The reset is coming from somewhere else, so focus on finding that.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
nogema
Associate II

Thank you for your answers !

To configure the timer, I use the MX_TIM2_Init function generated by the .ioc file in main.c :

void MX_TIM2_Init(void)
{
 
  /* USER CODE BEGIN TIM2_Init 0 */
 
  /* USER CODE END TIM2_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM2_Init 1 */
 
  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 1000;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 24000;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
 
  /* USER CODE END TIM2_Init 2 */
 
}

I use the function HAL_TIM_Base_Start_IT(&htim2) to start the timer in the function HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin).

Finally, I add the function HAL_TIM_PeriodElapsedCallback :

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
    nbCycle++;
    HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    //fin du timer
    if(nbCycle == NBCYCLE){
    	//si le nombre de pression n a pas ete atteint avant la fin timer
    	if(nbPression != 0){
    		//on reinitialise le compteur de pression
    		nbPression = 0;
    	}
    	//on arrete le timer
	HAL_TIM_Base_Stop_IT(htim);
	//on reinitialise le compteur de cycle
	nbCycle = 0;
	timerLance = 0;
	EnterStop2Mode();
    }
}

> you can't just write to the ARR register (are ARE writing to the ARR register, correct?), you also need to trigger an update to make that new value "active"

I don't understand what you make reference @Bob S​ 

nogema
Associate II

PROBLEM SOLVED :

I removed MX_LoRaWAN_Init() and MX_LoRaWAN_Process() functions in the main loop, then the timer TIM2 ran correctly. When I added again those functions, the timer had bad cycles. So the problem came from the LoRaWAN middleware. Then I remembered I already used a timer to send periodicaly data. To do that, I used the utilities timer with UTIL_TIMER functions.

So I disabled the timer TIM2, I created another timer with the UTIL_TIMER functions for my button and a callback function and it worked.

Thank you for your help

Piranha
Chief II

> the timer counts cycles of 1min30

As the TIM2 is 32-bit, then 2^32 / 48MHz = 89,5 s.

> you also need to trigger an update to make that new value "active"

One can do it by setting TIM_EGR_UG bit.