2
\$\begingroup\$

I'm working with an STM32F4 Discovery board and I've come across a bit of unusual behavior that I'm hoping someone can explain the cause of to me. My goal is to configure a timer to trigger an interrupt at 100 Hz (i.e. 10 ms period). It's important for my project to have this value be as close to 10 ms as possible. My system clock is configured at 168 MHz, and the timer I'm using is clocked on the APB2 bus, which is clocked at 84 MHz, but since timers operate at double their bus's clock speed, my timer's clock is effectively also at 168 MHz.

To get my period of 10 ms, I would have to configure my prescaler and period values in the TIM_TimeBaseInitTypeDef struct to 16-bit integer values. The initial values I chose were 60000 for the prescaler, and 28 for the period. 168 MHz / 60K = 2800 Hz. Then setting my period to 28 should give me an update event at 100 Hz.

I'm fairly positive that my math checks out, however, when I measured out the time when my interrupt was firing, my period was something closer to 10.33 ms, rather than the expected 10 ms. After playing around with other settings, I decided to try and change the prescaler and period values to see if the timing settings changed. To my surprise, they did. For the period values that I did try, I plotted them out in this plot below: scatterchart

Two main observations that I see:

1) Swapping the period for the prescaler and vice versa results in the same measured period

2) The closer the period and prescaler values are to each other, the closer the measured time is to the desired period.

Does anyone know why this is? It seems to me there's no difference between the pair (60000,28) and (1344,1250) in terms of calculating the period (i.e. they both multiply to 1680000)

Edit: I've added a link to my code here.

Edit2: I feel like the comments are deviating from my intended question. My issue isn't that I can't get a 10 ms period. My question is WHY setting the prescaler and period to values further apart from each other results in a less accurate period?

\$\endgroup\$
  • \$\begingroup\$ Mate, i think you are having integer overflow? The max number for 16 bit unsigned integer is 65,535. You should cast all numbers and operations that need to result in larger than this to an unsigned long. \$\endgroup\$ – KyranF Oct 16 '14 at 20:34
  • \$\begingroup\$ @KyranF Thanks for the reply. I'm skeptical that it's an issue of integer overflow. I specifically made sure that the largest prescaler value I worked with was 60,000, which is within range? \$\endgroup\$ – HD_Mouse Oct 16 '14 at 20:39
  • 1
    \$\begingroup\$ @HD_Mouse how are you taking your measurements? And are you measuring from the previous occurrence, or cumulative from the start time, or number of occurrence per unit time? You should expect some jitter in instance-to-instance measurements due to interrupt latency and other possibly higher priority interrupts, but error should average out, not accumulate over time. \$\endgroup\$ – Chris Stratton Oct 16 '14 at 20:56
  • 2
    \$\begingroup\$ Sorry I don't have time to check right now, but I am thinking that you need to subtract 1 from timer and prescaler calculated settings. I have to go ... \$\endgroup\$ – Tut Oct 16 '14 at 20:59
  • 2
    \$\begingroup\$ Let's see if we can get @Tut back here to claim credit for first mentioning the issue. \$\endgroup\$ – Chris Stratton Oct 16 '14 at 21:32
3
\$\begingroup\$

As Tut was first to suggest, the observed error arrises from the fact that the total number of cycles in these dividers is one more than the value loaded into the corresponding register.

You took this into account in the prescaler register, but not in the period register.

When you apportion the net division equitably between the two stages, each has a moderately large value and so the effect of "off-by-one" is small.

But when you apportion the division unequally such that one value is only 28, the difference between 29 counts (28+1) vs the correct 28 (27+1) is responsible for the 1-part-in-28 error you see.

\$\endgroup\$
0
\$\begingroup\$

It actually divide frequency as:

$$ f = \frac{168~MHz}{(60000+1)\cdot(28+1)} = 96.55~Hz \\ T = 10.36~ms $$

If you want 10Hz, please try to set prescaler = 59999, period = 27; then the timer will work as

$$ f = \frac{168~MHz}{(59999+1)\cdot(27+1)} = 100~Hz $$

It's a rule from STM specification.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.