Question
Function to calc PSC and ARR for a desired frequency, fairly fast!
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