cancel
Showing results for 
Search instead for 
Did you mean: 

Creating software based retriggerable one pulse timer

HZaib.1
Associate III

Hi, I want to create a timer with retriggerable pulse of specified length. 

Now I know timer can do it, but there is an issue with one pulse retriggerable mode that needs to be from outside trigger otherwise it dont work. My application is specific and it needs retriggerable mode but internally not from external source. Now the simple solution would be give gpio to one of the sources and route it to that trigger pin and do that way, but the issue is PCBs are already manufactured and no changes can be made, so it is upto me to solve it in software now. 

 

Is there any software solution I can do mimic this oneshot pulse timer ? I tried other methods with output compare and stuff but that does not work well. 

1 ACCEPTED SOLUTION

Accepted Solutions
HZaib.1
Associate III

So I can confirm now after alot of testing that. Retriggerable timer cannot be done with software trigger update only from external source or internal timers it can be triggered. 

In the end after using 2 timers I was able to achieve what I was trying to do. 

 

Here is a screen shot what Retriggerable pulse looks like. 

Channel 0 is Retriggerable timer pulse 

 

HZaib1_0-1707530004372.png

So it is working quite well but not happy with how stm implemented this simple functionality with such a complication.

 

View solution in original post

11 REPLIES 11

Use TIM_EGR.TG to generate trigger event in software.

JW

Timer have feature of "software trigger". Just simply configure timer to retriggerable one-shot mode and trigger it by setting bit TG in register TIMx_EGR.

HZaib.1
Associate III

Thank you for quick reply. 

I am still little bit confused. 

So according to datasheet it is said that the timer needs to be in combined reset + trigger mode .

HZaib1_0-1707333588073.png

So in cubemx i selected following options

HZaib1_1-1707333633644.png

 

in case of my initialization code i changed the period value to 1ms pulse 

 

  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
	  TIM_MasterConfigTypeDef sMasterConfig = {0};
	  TIM_OC_InitTypeDef sConfigOC = {0};

	  /* USER CODE BEGIN TIM4_Init 1 */

	  /* USER CODE END TIM4_Init 1 */
	  htim4.Instance = TIM4;
	  htim4.Init.Prescaler = 1000;
	  htim4.Init.CounterMode =TIM_COUNTERMODE_UP;
	  htim4.Init.Period = kaBaud10bit_STM[iBaud] + kaBaud10bit_STM[_38400BaudI];
	  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  if (HAL_TIM_OC_Init(&htim4) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  if (HAL_TIM_OnePulse_Init(&htim4, TIM_OPMODE_SINGLE) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_COMBINED_RESETTRIGGER;
	  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
	  if (HAL_TIM_SlaveConfigSynchro(&htim4, &sSlaveConfig) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
	  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  sConfigOC.OCMode = TIM_OCMODE_RETRIGERRABLE_OPM2;
	  sConfigOC.Pulse = 0;
	  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
	  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
	  if (HAL_TIM_OC_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
	  {
	    Error_Handler();
	  }
	  /* USER CODE BEGIN TIM4_Init 2 */

	  TIM_CCxChannelCmd(htim4.Instance, TIM_CHANNEL_3, TIM_CCx_ENABLE);

	  __HAL_TIM_ENABLE(&htim4);
	  HAL_TIM_OnePulse_Start(&htim4, TIM_CHANNEL_3);

	//  htim4.Instance->EGR |= TIM_EGR_TG;


	  //__HAL_TIM_ENABLE(&htim4);

	  /* USER CODE END TIM4_Init 2 */
	  HAL_TIM_MspPostInit(&htim4);

 

 

now when ever I want to trigger it i use this statement htim4.Instance->EGR |= TIM_EGR_TG; to enable the pulse to go high for 1ms or more but that does not happen and once the pulse trigger it does not trigger back

HZaib1_2-1707333846490.png

 

 

Describe, what do we see on that captured waveform, and how is it different from the expectations.

Read out and check/post content of TIM registers.

JW

HZaib1_0-1707357460637.png

ignore the first pulse as it is just from reset and some noise

 

as you can see from pulse in red circle. i invoked the timer trigger once but after that i could not  trigger it and timing was also not what I set.

In debugger, read out content of TIM registers just before first triggering (which does produce the pulse) and before the next attempt to trigger (which does not produce the pulse), and compare/post.

JW

I've tested that "new" retriggerable mode and it looks like it is not able to SW trigger.
Old ("nonretriggerable") one pulse mode can be triggered by setting TIM_CR1_CEN and then TIM_EGR_TG.
but new "retriggerable mode" ignores the same pattern (CEN+TG), and also TG. But when i generate Trigger from another timer (TRGO) it works. If i am right, there is need to workaround. For example use anothe timer in old (nonretriggerable) one pulse mode and use its TRGO output (selected as trigger event) to propagate trigger to second timer in retriggerable mode... may be i am wrong. If you find a way to trigger retriggerable mode by SW, I'd love to see it.

From my point of wiev the easiest way how to implement software "retriggerable" mode is to use nonretriggerable mode and:
1. clear CNT register (retrigger if timer still run)
2. set CEN (trigger if timer is stopped, ignored if run)
3. set TG (trigger if timer is stopped, ignored if run)
to "retrigger". But i am not sure if there isnt some kind of race condition (for example CEN cleared between steps 2 and 3, but step 1 should care of it ?). 

> I've tested that "new" retriggerable mode and it looks like it is not able to SW trigger.

Huh!

Which STM32?

JW

Thanks alot for your explanation, really appreciate it. 

Yes thats what I thought according to reading through datasheet, thats what I was thinking that software triggering for it is not possible. 

 

I will try your said implementation and also try it triggering from another timer. And post update here

 

My use case for this timer is bit tricky as my main purpose for this to trigger DE pin for rs485. Now you might be thinking why i am not simply toggling it when transmitting or receiving simple enough, but in my project due to quite precise timing of multiple communications due to that following implementation is not working. And the idea for triggering through retriggerable timer i got it from someone who implementated same thing for rs485 communication with onepulse retriggrable timer and for his usecase also the timing were quite precise, but the controller for that was of renesas and implementing it was quite easy. 

 

Now stm32l4 already have feature of uart rs485 hardware control, with that my system actually works but there are still issues with it also.