6
\$\begingroup\$

This is a subject that seems to have a lot of confusion (I do not fully understand). How to calculate the Variables:

  • Period
  • Prescaler
  • Duration

if only a few other variables are known. At higher frequencies, for example 1000000Hz simple rules work. At lower Frequencies like 1281Hz things get a little more complicated.

As an example: if we aim for an output frequency of 1281Hz, we need to set the ARR Register to: 32785. We need to set the PSC Register to: 3 and if we want a 50% DutyCycle, we need to set the CCRx Register to: 16393. Where the x in CCRx is the specified Channel one is going to use. 1, 2, 3 or 4.

The Registers need to see values of 16 BITs, Integer Values(65535 or less).

Equations exist so calculations can be made, for example:

\$TIM_{Update Frequency(Hz)} = \frac{Clock}{(PSC - 1) * (Period - 1)}\$

\1281ドル.11273792094 = \frac{84000000}{3 * 32785} \$

now, the problem becomes more complicated, for a desired frequency of 840Hz:

\425ドル.946209078739 = \frac{84000000}{167 * 1189}\$

Here in lies the problem, how does one find the value of PSC when one knows only the values for "Clock" and "Period"? The value "TIM_Update_Frequency(Hz)" is not always the actual Desired Frequency.

Other equations must exist so as to calculate the "PSC" Value, or to calculate the "TIM_Update_Frequency(Hz)" so as to deduce the other values.

Guess work is just not a logical approach here.

Can anyone help with more equations for solving for the other variables?

Thank you

Chris

Connor Wolf
32.7k6 gold badges83 silver badges143 bronze badges
asked Oct 5, 2014 at 3:42
\$\endgroup\$
4
  • 2
    \$\begingroup\$ A couple of points. 1. Numbers usually have a character every 3 digits, to make it easier to parse. For example, 1000000Hz, using the GB/USA-English convention is easier to read written as 1,000,000Hz, or elsewhere 1 000 000Hz (or even 1_000_000). 2. There are SI unit Metric prefixes so 1000000Hz is easier to understand when it is written as 1MHz. 3. A typical crystal, used as the frequency source of an STM32, is accurate to 20 parts in 1 million or worse (2 in 100,000), so quoting numbers like 1281.11273792094, is misleading; 1281.11 is enough. \$\endgroup\$ Commented Oct 5, 2014 at 16:13
  • \$\begingroup\$ @gblumer - Yes I understand what your points are. However, many Function Generators do have 4 or 6 digit resolutions after the decimal point, expensive ones can have more. A nice example of this: ebay.com.au/itm/… put the numbers in after the decimal points really just to show that I was not messing with the numbers generated. Thank you, helpful post: +1. \$\endgroup\$ Commented Oct 5, 2014 at 20:32
  • \$\begingroup\$ That link leads to a ebay.com.au/itm/… device which says "Accuracy:±2ppm". It matters less where the decimal point is, and more how many significant figures are used. So "±2ppm" is only one more digit than a typical crystal, i.e. not 1281.11273792094 but only 1281.113. \$\endgroup\$ Commented Oct 5, 2014 at 20:55
  • \$\begingroup\$ I don’t understand the question, how can you know the period register value without knowing the prescalar value? The prescaler is to help achieve longer timer periods. Normally you start with a known system/peripheral clock and a desired timer frequency you then need to deduce the prescaler and timer period register values, is this what you are asking? \$\endgroup\$ Commented Sep 8, 2020 at 12:55

3 Answers 3

2
\$\begingroup\$

I have deleted my last answer because it was not correct all of the time. I have managed to use this equation to get correct results:

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

Factoring Numbers was not the answer.

Here is a simple method I am now using to work out the other variables, Period and Duration.

private void CalculateVariables()
 {
 // Set the Bus Speed (APB1 or APB2), all timers are APB1 except TIM1 and TIM8...
 if (PWMPin == CPU.Pin.Pin7_X3 || PWMPin == CPU.Pin.Pin9_X3 || PWMPin == CPU.Pin.Pin7_X4)
 {
 ClockSpeed = CPU.Clock.APB2;
 }
 else
 {
 ClockSpeed = CPU.Clock.APB1;
 }
 #region Fields...
 uint ONE_MHZ = 1000000;
 uint prescaler = 0;
 uint period = m_period;
 uint duration = m_duration;
 uint scale = ((uint)m_scale);
 // Scale in MHz... 
 uint scaleMHz = scale / ONE_MHZ;
 uint clk = ((uint)ClockSpeed / ONE_MHZ);
 if (duration > period) duration = period;
 #endregion
 #region Calculate Variables (This is a C# implimentation of GHI Source ("PWM_ApplyConfiguration"))...
 prescaler = clk / scale;
 if (prescaler == 0)
 {
 if (period > (0xFFFFFFFF / clk))
 {
 // Avoid Overflow... 
 prescaler = clk;
 period /= scaleMHz;
 duration /= scaleMHz;
 }
 else
 {
 prescaler = 1;
 period = period * clk / scaleMHz;
 duration = duration * clk / scaleMHz;
 }
 }
 else
 {
 while (prescaler > 0x10000)
 {
 // Prescaler too Large... 
 if (period >= 0x80000000) break;
 prescaler >>= 1;
 period <<= 1;
 duration <<= 1;
 }
 }
 bool TimerIs16Bit = true;
 // Were not using Timer 2 of Timer 5...
 if (TimerIs16Bit)
 {
 // All Timers are 16 bit Timer's except 2 and 5... 
 while (period >= 0x10000)
 {
 // period too large 
 if (prescaler > 0x8000) break;
 prescaler <<= 1;
 period >>= 1;
 duration >>= 1;
 }
 }
 #endregion
 if (debug)
 {
 Debug.Print("*** Scale *******");
 // Print to Debug window new config...
 Debug.Print("Period = " + period);
 Debug.Print("Prescaler = " + PrescalerFromPeriodFrequencyAndClock(period, this.Frequency));
 Debug.Print("Duration = " + duration);
 }
 ARRValue = (period - 1);
 PSCValue = PrescalerFromPeriodFrequencyAndClock(period, this.Frequency);
 CCRxValue = duration;
 }

a Simple static Class CPU and I have added:

public enum Pin : int
 {
 Pin7_X3 = 1,
 Pin8_X3 = 2,
 Pin9_X3 = 3,
 Pin7_X4 = 4,
 Pin8_X4 = 5,
 Pin9_X4 = 6
 }
answered Oct 11, 2014 at 22:54
\$\endgroup\$
2
\$\begingroup\$

Depending on the clock, prescaler and auto reload, repetition counter (if present) parameters, the 16-bit timer can generate an update event from a nanosecond to a few minutes.

For example, to generate an event two times per second, choose Clock frequency(TIM_CLK) = 168 Mhz, Prescalar(PSC) = 16799, Period(ARR) = 4999, repetition counter(RCR) = 0,

then the 16-bit timer will generate an event two times per second.

enter image description here

For more information ;

STM32 Timer Overview

answered Jul 26, 2017 at 21:00
\$\endgroup\$
0
\$\begingroup\$

There is a tool written in python to do all the calculations: https://github.com/v0idv0id/STM32-Scaler

answered Sep 8, 2020 at 9:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.