cancel
Showing results for 
Search instead for 
Did you mean: 

Timer One Pulse Mode Delay and Pulse

Lionel1
Associate II

Hi

Timer make me crazy !!!

Is there a simple formula to compute prescaler and ARR for a defined Delay and Pulse ?

I have a STM32F411 Nucleo at 100 MHz. For the Timer2, APB1 is at 50 MHz.

I want a delay of 10 ms with a pulse of 50 us.

Thanks

Lionel

Note : why CubeMX has not a tool for that and in general to compute prescaler and ARR for a any period ?

9 REPLIES 9
S.Ma
Principal

Hmm if you prescale 50 (writing 49=50-1) one tick will be 1 usec.

1000 = 1 msec

10000 = 10 msec

Pulse will be 50 counts.

16 bit timer will be good enough and debugging will be easy as 1 us = 1 timer tick ?

If APB1 is prescaled /2, TIM2's clock will be APB1 clock * 2.

JW

Hi

Yes ... but no !!

That's what I try first but in fact Pulse is not what you think ! In fact "my pulse" = ARR - STM32 Pulse.

So, we have in fact :

PSC = 49 : This is OK, TIM2 Clock = 50 MHz (APB1 is prescaled by 4), so tick = 1us

ARR = 10049 (10050 - 1)

Pulse = 10000

Then we have "my pulse" = 10050 - 10000 = 50 ticks = 50 us 😀

and "my delay" = 10000 ticks = 10000 us = 10 ms 😀

Now, another problem. I want to change dynamicaly the delay (pulse stay equal). What is the best way to do that ? Shall I stop and restart the timer each time ? Is it possible to have an interrupt at the end of the pulse to make the change ?

Lionel

Well we don't know much of the plumbing.

Is the timer free run? triggered from signal?

If you want something very flexible with HW assist, get the luxury of a TIMER which channels can be updated by DMA. In the non elegant start, cycle through 2 compare values toggling the output. then you can decide to change the PWM position at the end of the pulse (DMA looping). you can also let the DMA swap between 2 tables, etc...

With such HW assist, even if you stop the code with a breakpoint for debugging, if the timer is running, pulses will still be generated...

> Now, another problem. I want to change dynamicaly the delay (pulse stay equal). What is the best way to do that ?

Make it the other way round, i.e have the pulse at the beginning of the timer's period (PWM mode 1). In this way, you keep TIMx_CCRx constant (ie. 50) and change only TIMx_ARR. It's a good idea to have ARR preloaded (i.e. TIMx_CR1.ARPE=1), in that way the value written into TIMx_ARR gets effective in the next period of timer, and there's no risk of writing TIMx_ARR to a value lower than current TIMx_CNT which would result in an unexpectedly long period, until TIMx_CNT wraps around.

> Is it possible to have an interrupt at the end of the pulse to make the change ?

The update interrupt occurs when TIMx_CNT gets cleared after reaching TIMx_ARR, i.e. at the beginning of the timer's period.

JW

Lionel1
Associate II

Hi

Many thanks for all your answers, it open others perspectives. I will try to be more precise with my project but sorry for my poor English !

Indeed, timer is triggered by an external signal each 10 ms (it is the zero crossing of an 50 Hz AC current). Now, I use TIM3 and the CubeMX configuration is :

Slave Mode : Trigger Mode

Trigger Source : TI2FP2 (=PB5)

Clock Source : Internal Clock

Channel 1 : PWM Generation CH1 (=PA6)

One Pulse Mode checked

I also use Channel 4 in PWM Generation for a led (I would like to have the intensity inverse proportional to the delay).

The pulse can not be at the beginning of the timer's period because it is the command of an SSR (Solid State Relay) and I want he start at a precise moment in the sinus wave of the AC current.

The computation of this precise moment (= the delay) is done in another place in the program.

So, what will be great should be :

  • I store the ARR and pulse I have computed in a DMA
  • just after the pulse, Timer read the new ARR and Pulse for the next cycle

Great, but I have no idea to do that !

Note : I am not familiar with register (I use CubeMX), so could you precise the correspondence between register name and CubeMX name.

Thanks,

Lionel

You don't need DMA, it's enough to change both ARR and CCR before any of them gets used in the given cycle, In the case you've described, i.e. CCR being set at 10ms and ARR at 10ms+50us, you can do it in an update interrupt (i.e. when the cycle starts); if the interrupt's latency plus time to store the two registers (including any other interrupts which may have higher priority) is lower than 10ms then you are OK.

> I am not familiar with register (I use CubeMX), so could you precise the correspondence between register name and CubeMX name.

No, Registers are the reference. It's your problem that you are using Cube/CubeMX.

JW

Lionel1
Associate II

Hi,

That's what I though, normally I have enough time to do the update after the pulse. So I have activated the interrupt but problem, no callback was called : I try "HAL_TIM_PWM_PulseFinishedCallback" who is logically what I need but nothing :(

A precision : 10 ms is the period between two triggers of the external signal. So the delay+pulse will be always less.

I agree with you, register is the good way but mistake come so fast when you are not familiar ! CubeMX is very useful to avoid many mistakes.

Lionel

Lionel1
Associate II

Arghhh, so stupid I am !

I use HAL_TIM_Base_Start in place of HAL_TIM_Base_Start_IT

Now, it works. I can use __HAL_TIM_SET_AUTORELOAD and __HAL_TIM_SET_COMPARE to update the parameters 🙂

Thanks for your help.

Lionel