cancel
Showing results for 
Search instead for 
Did you mean: 

Function to calc PSC and ARR for a desired frequency, fairly fast!

jason22
Associate II
Posted on May 20, 2012 at 20:02

The input to this function is a 'Desired Frequency' and the function, fairly quickly locates (out of the 4 billion possibilities! (ARR(16bit)*PSC(16bit)) the correct values for a given TIMER'S PRESCALER(PSC) and PERIOD(ARR) such that you get the TIMER as close as possible to your 'Desired Frequency.'

I just thought someone could use this, I have integrated this into my PHP web interface, but since it is practically C code, you guys could use it with little modification. Enjoy... Example outputs: 'Prescaler set at 0x2BFF uC Response: PSC=P00002BFF Period set at 0x0153 uC Response: ARR=A00000153 Desired Frequency = 11 Found Frequency = 000071500465, Prescaler = 2BFF, Period = 0153'' ''Prescaler set at 0x0005 uC Response: PSC=P00000005 Period set at 0x0054 uC Response: ARR=A00000054 Desired Frequency = 100000 Found Frequency = 100000, Prescaler = 0005, Period = 0054''

function
SetTimeBase(
$fdes
)
{
$fclk
= 168000000;
$period
= 65535;
$fd
=0;
$ff
=0;
$z
=0;
for
(
$p
=1; 
$p
<=65536; 
$p
++)
{
$f
= ((
$fclk
/2)/
$p
);
$x1
=3;
$x2
=65535; 
for
(
$t
=0; 
$t
<16; 
$t
++)
{
$x3
=
floor
((
$x2
-
$x1
)/2);
$x4
=
$x3
+
floor
((
$x2
-
$x3
)/2);
$x5
=
$x3
-
floor
((
$x3
-
$x1
)/2);
if
((
$x4
+1)%3 == 0)
{
$x4
+= 1;
}
else
if
((
$x4
-1)%3 == 0)
{
$x4
-= 1;
}
if
((
$x5
+1)%3 == 0)
{
$x5
+= 1;
}
else
if
((
$x5
-1)%3 == 0)
{
$x5
-= 1;
} 
if
((
$x4
> 0) && (
$x5
> 0))
{
if
(
abs
((
$f
/
$x4
/2)-
$fdes
) < 
abs
((
$f
/
$x5
/2)-
$fdes
))
{
$x1
= 
$x3
; 
}
else
{
$x2
= 
$x3
;
}
}
else
{
break
;
}
}
if
((
$x4
> 0) && (
$x5
> 0))
{
if
(
abs
((
$f
/
$x4
/2)-
$fdes
) < 
abs
((
$f
/
$x5
/2)-
$fdes
))
{
$x
= 
$x4
;
}
else
{
$x
= 
$x5
;
}
$ftmp
= (
$f
/
$x
/2);
$fdif
= 
abs
(
$fdes
-(
$f
/
$x
/2));
if
(
$z
== 0)
{
$fd
= 
$fdif
;
$ff
= 
$ftmp
;
$xx
= 
$x
;
$pp
= 
$p
;
}
if
(
$fdif
< 
$fd
)
{
$fd
= 
$fdif
;
$ff
= 
$ftmp
;
$xx
= 
$x
;
$pp
= 
$p
;
}
$z
++; 
}
}
if
(
$pp
<= 0xFFFF && 
$xx
<= 0xFFFF && 
$pp
> 0 && 
$xx
> 0)
{
$pp
= 
strtoupper
(
str_pad
(
dechex
(
$pp
),4,
''0''
,STR_PAD_LEFT));
$output
.= 
''Prescaler set at 0x$pp<br>uC Response: PSC=''
;
$output
.= shell_exec(
''./test.sh psc=0x''
.
$pp
.
'' 9''
).
''<br />''
;
usleep(100);
$xx
= 
strtoupper
(
str_pad
(
dechex
(
$xx
),4,
''0''
,STR_PAD_LEFT));
$output
.= 
''Period set at 0x$xx<br>uC Response: ARR=''
;
$output
.= shell_exec(
''./test.sh arr=0x''
.
$xx
.
'' 9''
).
''<br />''
; 
}
else
{
$pp
= 
strtoupper
(
str_pad
(
dechex
(
$pp
),4,
''0''
,STR_PAD_LEFT));
$xx
= 
strtoupper
(
str_pad
(
dechex
(
$xx
),4,
''0''
,STR_PAD_LEFT));
$output
.= 
''Frequency is out of bounds!<br>Error codes: PSC=0x$pp,ARR=0x$xx<br />''
;
}
$output
.= 
''Desired Frequency = $fdes<br />Found Frequency = $ff, Prescaler = $pp, Period = $xx<br />''
;
$objResponse
= 
new
xajaxResponse();
$objResponse
->assign(
''SomeElementId''
,
''innerHTML''
, 
$output
);
return
$objResponse
;
}

#timer #timer #timer-calculate-psc-arr-stm32f4
7 REPLIES 7
bjfree
Associate II
Posted on May 21, 2012 at 02:10

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6gP&d=%2Fa%2F0X0000000bt9%2FgXeGsKYnX_UHUcoK1kPgQz9DdhMmarcNC_2Vx2pI23o&asPdf=false
sajeed
Associate II
Posted on February 11, 2013 at 16:29

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6ma&d=%2Fa%2F0X0000000bvN%2FULa4qDO3Dpl9pFHjGWnZ3gaAJlaGHGFQKDCliv5LjNQ&asPdf=false
Posted on February 11, 2013 at 19:35

It is an exercise in factoring. You figure out the divisor for your input vs output clock, and generate two integer factors that multiplied together get you close to the desired divisor. I'd wade into the code, but I'm not that invested. When working with floats, fabs() might be closer to the documented behaviour of the PHP abs() function.

Do you need to do this on the fly? Do you have specific a frequency or range of frequencies you wish to compute? Are you aware that the integer nature of the prescaler and period can preclude the generation of specific or accurate frequencies from the source clock
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sajeed
Associate II
Posted on February 12, 2013 at 06:22

Hi Clive

Yes I need it on the fly and the frequency range is from 5 Hz to 3 K Hz. Expecting some solution from you.

Thanks in advance

Sajeed

Posted on February 12, 2013 at 16:15

Expecting some solution from you.

That might have lost something in translation, but this isn't my project. You'll need to code or find a factoring routine.

@48MHz

3KHz = 48000000 / (1 * 16000)

5Hz = 48000000 / (200 * 48000)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sajeed
Associate II
Posted on February 13, 2013 at 10:49

Hi Clive

Thanks for the reply , this is helpful.

Sajeed

abuchholz91
Associate II
Posted on September 30, 2014 at 23:27

For those looking for a solution, I have started to make progress in a factoring routine (Very Simple) here:

/d6123d2c

All the best

  Chris