STM32F4 Timers - Calculation of Period and Prescale, and Generating 1 ms Delay

Ehsan Habib picture Ehsan Habib · Aug 18, 2018 · Viewed 20.8k times · Source

I am using STM32F407VGT6 with CubeMX.
So i was beginning with General purpose timers and i am stuck with prescale and period values.

Basically i want to generate a timer interrupt every n(where n=1,2,3..) ms and perform some tasks.
There is lot of variations in the formula to calculate the value of period and prescale

Some versions of formula are:

TIMupdateFreq(HZ) = Clock/((PSC-1)*(Period-1))
Update Event = TIM clk/((PSC+1)*(ARR+1)*(RCR+1))
Prescaler = ((((ClockSpeed) / ((period) / (1 / frequency))) + 0.5) - 1)

So coming to the question, My core clock is running at 168 MHz But i can see the Timer are connected to APB1 Bus which is running at 84 MHz.

I have tried a code which generates 1 ms delay(said by the author) and after using that values for prescale and period i generated a code which also generates 1ms Delay(by intuition - no scope).

The code uses prescale value of 41999 and a period of 1999.

So,
PSC - 41999
ARR - 1999
Apllying this to the second formula

Update Event = TIM clk/((PSC+1)*(ARR+1)*(RCR+1))

Update Event = 84000000/(42000*2000) = 1 (Is this 1ms Delay??)

OK so now i am trying to understand how this PSC = 41999 and Period = 1999 are selected?? Is it purely based on assumption as in whatever formula i use i have to assume one variable.?? How to calculate prescale and period if i want say 1.5 or 2.3 or 4.9 something like that precise timing.??

EDIT

Moreover when i used PSC=41999 and Period =999 The update event value is 2.

Update Event = 84000000/(42000*1000) = 2

But my delay is twice in every sec. i.e 500ms

and when i use PSC=39999 and Period =4199 The update event value is 0.5.

Update Event = 84000000/(40000*4200) = 0.5

and my delay 2 ms.

Thanks in advance

Answer

followed Monica to Codidact picture followed Monica to Codidact · Aug 18, 2018

TIMupdateFreq(HZ) = Clock/((PSC-1)*(Period-1))

This is obviously wrong. The counters go from 0 to the register value (inclusive), there are always one more cycles than the register value, not one less.

Update Event = TIM clk/((PSC+1) * (ARR+1) * (RCR+1))

This one is better, but general purpose timers don't have RCR registers. You can assume RCR=0, and omit *(RCR+1) from the formula.

Prescaler = ((((ClockSpeed) / ((period) / (1 / frequency))) + 0.5) - 1)

This attempts to round the result, when no integer solution is possible. More on it later.

Update Event = 84000000/(42000*2000) = 1 (Is this 1ms Delay??)

No, this is one second (1s) delay, or 1 Hz frequency.

how this PSC = 41999 and Period = 1999 are selected?

Take the simple formula,

Updatefrequency = TIM clk/((PSC+1)*(ARR+1))

rearrange it to

(PSC+1)*(ARR+1) = TIMclk/Updatefrequency

then you have a known value on the right hand side, but two unknowns on the left hand side. The trivial solution would be to set one of them, e.g. PSC to 0, and ARR to the right hand side value - 1.

Unfortunately most timers have 16 bit registers only, so this is not going to work when TIMclk/Updatefrequency > 65535. Both PSC and ARR must fall between 0 and 65535. You'd have to find a factorization that satisfies these constraints.

Let's see an example, you'd want a 2.3 seconds delay. Note that 2.3s is the period, not the frequency, so you'd need to put its inverse into the formula.

(PSC+1) * (ARR+1) = 84000000 / (1 / 2.3) = 84000000 * 2.3 = 193200000

Luckily there are lots of zeroes at the end, you can just pick e.g. 10000 as the prescaler (PSC=9999), and ARR becomes 19320-1 = 19319. If the desired ratio is not a nice round number, then you should resort to integer factorization, or write a small program to look for all possible divisors (for(i=0;i<65536;i++) ...).

It can also happen that there are no precise integer solutions at all, then you can still loop through all possible prescaler values, and see which one gives the smallest error.

Update Event = 84000000/(42000*1000) = 2

But my delay is twice in every sec. i.e 500ms

Note the dimensions. You are using frequencies in the formula, you are dividing the 84 MHz input frequency with some values, and get 2 Hz as a result. 2 Hz frequency means two events every second, so the events are indeed 500ms apart.