cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Series - Calculations of Timer Variables.

abuchholz91
Associate II
Posted on October 05, 2014 at 04:02

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) = Clock / (PSC - 1) * (Period - 1)

1281.11273792094 = 84000000 / ((3) * (32785)) 

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

425.946209078739 = 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

#factoring!
13 REPLIES 13
Posted on October 05, 2014 at 06:43

http://coolmath.com/algebra/04-factoring/01-what-is-a-factor-01.htm

So 840 Hz, from 84 MHz, should be simple

84000000 / 840 = 100000

100000 = 10 * 10000

Prescaler = 10 - 1;

Period = 10000 - 1;

Pulse = 10000 / 2; // 50/50 duty

Pulse = 10000 / 4; // 25/75 duty
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
abuchholz91
Associate II
Posted on October 05, 2014 at 07:35

@Clive - This is not working for me. If the Frequency I am aiming for is above 1283Hz then this does work, below its not.

I have written the values into the Registers that you provided as a test and I get 1680Hz - Please help...

This is the part of the problem I was mentioning above: ''At higher frequencies, for example 1000000Hz simple rules work. At lower Frequencies like 1281Hz things get a little more complicated.''

Thanks for your help, I would really like to solve this issue.

All the best

  Chris

Posted on October 05, 2014 at 07:43

That would suggest you are using an APB2 timer clocking at 168 MHz. APB2 might be at DIV2 (84 MHz), but TIMCLK will be at DIV1 (168 MHz). See Clock Tree

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
abuchholz91
Associate II
Posted on October 05, 2014 at 08:05

abuchholz91
Associate II
Posted on October 05, 2014 at 11:15

@Clive - Well, it took me a little while for what you wrote to click. Yes I now understand and so far all testing is working.

// *******************************************************************

168000000 / 840 = 200000

200000 = 20 * 10000

this.Period = (10000 - 1);

this.Prescalar = (20 - 1);

this.Duration = (10000 / 2);

Output Frequency: 840Hz

// *******************************************************************

168000000 / 160 = 1050000

1050000 = 105 * 10000

this.Period = (10000 - 1);

this.Prescalar = (105 - 1);

this.Duration = (10000 / 2);

Output Frequency: 160Hz

// *******************************************************************

168000000 / 23456 = 7162.3465211459754433833560709413

7162.3465211459754433833560709413 = 2 * 3581

this.Period = (3581- 1);

this.Prescalar = (2 - 1);

this.Duration = (3581/ 2);

Output Frequency: 23.46KHz

// *******************************************************************

So, simple you were right, my in-experience did over look this Clock issue by the looks of it. Some confusion entered the picture: 168000000 / 2 = 84000000 - I real all over the web that APB2 was 84000000 and it is but the calculation you gave is not for the divider product, its for the Clock for APB2. 84000000 is only CK_CNT, not the APB2 Bus Speed: clock frequency = 168000000.

Factoring:

 

 

I have written, with some help of quite a few of the good folk's @Stack Exchange, a small application that may help others:

C# Console App:

        static void Main(string[] args)

        {

            double a;

            UInt32 Clk = 168000000;

           

            Console.WriteLine(''Please enter Frequency: '');

            a = uint.Parse(Console.ReadLine());

            // See: P.151 of the STM32F4xx RM0090 User Manual...

            // Several prescalers are used to configure the AHB frequency, the high-speed APB (APB2)

            // and the low-speed APB (APB1) domains. The maximum frequency of the AHB domain is

            // 180 MHz. The maximum allowed frequency of the high-speed APB2 domain is 90 MHz. The

            // maximum allowed frequency of the low-speed APB1 domain is 45 MHz

            Console.WriteLine(''APB1 Low speed Advanced Peripheral Bus'');

            Console.WriteLine(''APB2 High speed Advanced Peripheral Bus'');

            uint PxQ = (Clk / Convert.ToUInt32(a));

            List<uint> list = Factor(PxQ);

            for (int i = 0; i < (list.Count); i++)

            {

                if (list[i] >= 65535)

                {

                    Console.WriteLine(''Factor is too large: {0}'', list[i]);

                }

                else

                {

                    if (0 != (i % 2))

                    {

                        Console.WriteLine(''Freq {0} = ({1} (Clk) / {2} = Factored Numbers: (P = {3} * Q = {4}))'', a, Clk, PxQ, list[i - 1], list[i]);

                    }

                }

            }

            Console.ReadLine();

        }

        /// <summary>

        /// Thanks to those involved in getting this excellent Function together!!!

        /// See:

http://stackoverflow.com/questions/239865/best-way-to-find-all-factors-of-a-given-number-in-c-sharp

        /// This Function has been slightly modified by myself to suit the purposes of this application.

        /// </summary>

        /// <param name=''number''>Number to get the Factored Numbers for. E.G: (3 * 2) = 6. 6 Being the Number.</param>

        /// <returns>List<uint></returns>

        public static List<uint> Factor(uint number)

        {

            List<uint> factors = new List<uint>();

            // Round down the Number to check...

            uint max = (uint)Math.Sqrt(number);

            for (uint factor = 1; factor <= max; ++factor)

            {

                // Test from 1 to the square root, or the int below it, inclusive...

                if (number % factor == 0)

                {

                    factors.Add(factor);

                    if (factor != number / factor)

                    {

                        // Don't add the square root twice!  Thanks Jon

                        factors.Add(number / factor);

                    }

                }

            }

            return factors;

        } Thank You Clive for your help - ST Should put you on staff!!!

All the Best

  Chris

Posted on October 05, 2014 at 14:43

The TIMCLK is typically twice the APB clock, it's often useful for timers to clock as fast as possible.

On the F4 running at 168 MHz, APB1 is typically 42 MHz (DIV4) and APB2 84 MHz (DIV2), and the respective TIMCLKs are 84 MHz, and 168 MHz.

The APB2 timers are ALL 16-bit, presumably due to the cost of clocking a 32-bit counter at 168 MHz

0690X00000605AfQAI.png
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
abuchholz91
Associate II
Posted on October 05, 2014 at 23:49

@All - Some equations that I hope will help others. It has taken me a fair while to get this topic right. I hope this helps others.

UPDATE: JW has kindly provided Document numbers that show some equations:

The update event period is calculated as follows:

Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR + 1))

Where: TIM_CLK = timer clock input

PSC = 16-bit prescaler register

ARR = 16/32-bit Autoreload register

RCR = 16-bit repetition counter (where present)

Thanks JW.

URL:

http://www.st.com/web/en/resource/technical/document/application_note/DM00042534.pdf

0690X00000605AkQAI.png

abuchholz91
Associate II
Posted on October 06, 2014 at 03:43

@Clive - After some more testing, I am getting the odd few issues. This does not make sense to me!

@1840Hz I get 1.227KHz output. The Math below.

168MHz / 1840 = 91304

168MHz / (2 * 45652) = 1840.Hz

So I am still having issues. Its almost like there is a Clock Divider that kicks in at a certain frequency's.

All the Best

  Chris

EDIT:

 

Another frequency: 184Hz

PSC = 16

ARR = 57065

168MHz / (16 * 57065) = 184.00...

But instead, I get: 173.2Hz

Posted on October 06, 2014 at 08:37

Instead of spawning various equations with arbitrarily chosen variable names, why don't you resort to the STM32 documentation, namely the timer chapters in user manuals and application notes, e.g. AN4013?

The update event period is calculated as follows:

Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR + 1))

Where: TIM_CLK = timer clock input

PSC = 16-bit prescaler register

ARR = 16/32-bit Autoreload register

RCR = 16-bit repetition counter (where present)

JW