I want to set frequency of a timer in a microcontroller. Frequency is determined by Prescaler and Period (ARR). Both of these are 16bit integer numbers.
$$f_{tim}=\frac{f_{clock}}{prescaler\cdot period}$$
Can you suggest an efficient way (not just trying all possible values) to find values that result in frequency as close as possible to the desired one?
-
\$\begingroup\$ Prescaler values are usually quite restricted, e.g. to powers of 2. So the first step is to discover what the restrictions are, from the MCU's datasheets and programming guides. \$\endgroup\$user16324– user163242021年09月12日 18:55:18 +00:00Commented Sep 12, 2021 at 18:55
-
\$\begingroup\$ As I said: Prescaler is any 16bit unsigned integer. (STM32L4) \$\endgroup\$Jiří Maier– Jiří Maier2021年09月12日 19:08:38 +00:00Commented Sep 12, 2021 at 19:08
-
2\$\begingroup\$ then you are looking for factorisation algorithms. \$\endgroup\$user16324– user163242021年09月12日 20:25:05 +00:00Commented Sep 12, 2021 at 20:25
-
1\$\begingroup\$ obviously you dont need to try all possible values. the smaller the prescaler the more accurate it is going to be, so you dont need to try all possible values, but can quickly narrow in on the solution without too many iterations. couple of easy ways to do that. \$\endgroup\$old_timer– old_timer2021年09月13日 01:18:54 +00:00Commented Sep 13, 2021 at 1:18
-
\$\begingroup\$ Since prescaler and period are both integers, their product is also an integer. As @user_1818839 said, it's a factorisation problem; apply mathematics. If you can, define the clock frequency as a integer multiple of the timer frequency. Would you mind to edit your question providing some more context? \$\endgroup\$the busybee– the busybee2021年09月13日 09:32:46 +00:00Commented Sep 13, 2021 at 9:32
1 Answer 1
See if you like this version better.
A set of two integer factor (X & Y), that produce closest integer to a real number (N).
In case, factors of N do not exist, or factors are not usable:
Consider a division, N / X = Y + R, where X and Y are integer, and R is a remainder.
Since, R < X, the smaller divisor (X) is, the smaller remainder (R) results.
Meantime, from X * Y ~ N, the larger Y gets, the smaller X is.
Thus, Find the largest Y, then calculate X.
A random example:
Clock speed: 16Mhz
Prescaler: 16bit
Divider: 8bit
Desired output frequency: 115Hz
Operation:
Scale = 16Mhz / 115Hz = 139130.4348 ---(1)
The largest from the 16bit prescaler (Y) = 65535 ---(2)
The smallest divisor, X = N / Y = 139130.4348 / 65535 = 2.122994 ---(3)
Since Y cannot be larger, X = 3 ---(4)
Thus, recalculating, N / X = 139130.4348 / 3 = 46376.81159, Y = 46377 ---(5)Output clock = 16Mhz / (46377 * 3) = 16Mhz / 139131 = 114.999532814 ---(6)
-
\$\begingroup\$ Now, I see @old_timer gave the answer already. Sorry about that. \$\endgroup\$jay– jay2021年09月14日 15:57:58 +00:00Commented Sep 14, 2021 at 15:57
-
\$\begingroup\$ Tkank you for answer. However I am still not convinced that this gives the best possible values. It Is clear that R < X, so small X is guaranteed to have small R, but R could be even smaller "by chance" for any large X. \$\endgroup\$Jiří Maier– Jiří Maier2021年09月15日 16:22:40 +00:00Commented Sep 15, 2021 at 16:22
-
\$\begingroup\$ Correction: but R*X could be even smaller "by chance" for any large X there may even be a value of X for which R is zero. \$\endgroup\$Jiří Maier– Jiří Maier2021年09月15日 16:28:33 +00:00Commented Sep 15, 2021 at 16:28
-
\$\begingroup\$ @JiříMaier Yes, R could be zero, if appropriate factors exist. You do not need to hand factorize. Search for "factor calculator". \$\endgroup\$jay– jay2021年09月15日 16:33:11 +00:00Commented Sep 15, 2021 at 16:33