cancel
Showing results for 
Search instead for 
Did you mean: 

Change Period of a timer dynamically

SSchu.4
Associate II

I am experimenting with timers...

I have a list of time values that I want to use to replay a digital signal.

What I try to do is to wait for the interrupt of the base timer, then set a new

period value, then wait for the next interrupt.

But it seems I do something wrong.

Timer init

htim6.Instance = TIM6;
  htim6.Init.Prescaler = 49;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 65530;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

Timer interupt

 if(htim->Instance == TIM6){
 
	  if(cmd == 1){
		  HAL_GPIO_TogglePin(IR_SND_GPIO_Port, IR_SND_Pin);
                  // tried without stop/start - did not change
		  HAL_TIM_Base_Stop_IT(&htim6);
		  __HAL_TIM_SET_AUTORELOAD(&htim6,vol_up[sq++]);
                  // did not do that - no change
		  __HAL_TIM_SET_COUNTER(&htim6,0);
		  HAL_TIM_Base_Start_IT(&htim6);
		  __NOP();
	  }
  }

This works for the first value, but then I get interrupts at a more or less random pattern.

The values got up and down in my array (between 600 and 1600). I tried with and without Stop/Start and with/without __SETCOUNTER__ - no change as well.

Ideas are highly appreciated

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

Where and how are cmd, vol_up and sq declared? All of them should be volatile if they are touched both inside and outside an interrupt handler.

View solution in original post

10 REPLIES 10

With autoreload preload set, your freshly set TIMx_ARR doesn't get active until the next update event (i.e. counter "overflow").

That might be surprising but still shouldn't be random.

I don't understand the Cube/HAL gobbledygook so maybe I'm overlooking something.

JW

TDK
Guru

Just doing

 		  __HAL_TIM_SET_AUTORELOAD(&htim6,vol_up[sq++]);

without the other stuff should do what you want. If you reset the counter to 0, you're not going to get even periods.

Also need to ensure the periods are long enough that your interrupt finishes before the next one fires.

If you feel a post has answered your question, please click "Accept as Solution".
berendi
Principal

Where and how are cmd, vol_up and sq declared? All of them should be volatile if they are touched both inside and outside an interrupt handler.

SSchu.4
Associate II

So, mystery solved. I did not realize that __HAL_TIM_SET_AUTORELOAD is a macro that expands to

 (__HANDLE__)->Instance->ARR = (__AUTORELOAD__);  \
 (__HANDLE__)->Init.Period = (__AUTORELOAD__);   

That caused my variable to be incremented twice, messing up my understandig :)

Solved now!

Never assume that a HAL function does what you think it should do.

A well deserved punishment for using Cube/HAL.

JW

SSchu.4
Associate II

I don’t know guys - actually it’s a C topic and a lack of understanding by myself.

i have quite good success with HAL so far - every time I thought It is buggy, it turned out the be my fault in the end.

well, YMMV and as a side Note, I think it’s Not helpful to see an error as a „well deserved punishment“. Actually this... oh well, forget it...

berendi
Principal

> every time I thought It is buggy, it turned out the be my fault in the end.

No. __HAL_TIM_SET_AUTORELOAD() doesn't do what its documentation says. In useless Captain Obvious one-liner style typical for HAL, it states

Set the TIM Autoreload Register value on runtime without calling another time any Init function.

failing to mention that it modifies something else too, and that it is a macro that evaluates both of its arguments twice.

If you have to examine the source code every time to call a function in a library, then this library is useless for production. A lot of your time is wasted on looking for unwanted side effects in HAL functions and working around them, instead of just setting a few registers.

Not to mention the huge overhead of all those complicated functions that are still nothing more just wrappers for register writes. Renaming register fields without reason and putting them in a temporary structure is not an abstraction.

> „well deserved punishment“... not helpful

I agree. I should've said "We see this frustration with Cube/HAL here often. Maybe you might want to consider, whether it's worth taking the risk of using the rather poorly documented facilities of Cube/HAL without further investigation, maybe fixing ad-hoc the cases when it obviously fails, with the risk of having your program failed later on a less obvious issue; or deconstruct its functionality meticulously every time you are going to use it AND every time you "update" the "library"; or simply ditch it and write programs in the normal way. Cube/HAL objectively does not represent a benefit of a significant weight, and has a long track of causing problems. Remember, once you've decided to use any "library" in your program, it's ultimately *your* responsibility whether they will cause your program to fail or not. That's what engineering prudence says anyway; lawyers might be of a different opinion but I Am An Engineer Not A Lawyer."

But it's longer and probably wouldn't carry the message across as aptly.

Exactly as you've said, YMMV.

JW