2014-10-04 07:02 PM
This is a subject that seems to have a lot of confusion (I do not fully understand). How to calculate the Variables:
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!2014-10-04 09:43 PM
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 duty2014-10-04 10:35 PM
@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 Chris2014-10-04 10:43 PM
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
2014-10-04 11:05 PM
2014-10-05 02:15 AM
@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 MHzConsole.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 Chris2014-10-05 05:43 AM
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 MHz2014-10-05 02:49 PM
@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
2014-10-05 06:43 PM
@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 ChrisEDIT:Another frequency: 184Hz PSC = 16 ARR = 57065 168MHz / (16 * 57065) = 184.00... But instead, I get: 173.2Hz
2014-10-05 11:37 PM
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