STM32 Series Microcontroller - Calculations of Timer Variables
I have deleted my last answer because it was not correct all of the time. I have managed to use this equation to get correct results:
Prescaler = ((((ClockSpeed) / ((period) / (1 / frequency))) + 0.5) - 1);
Factoring Numbers was not the answer.
Here is a simple method I am now using to work out the other variables, Period and Duration.
private void CalculateVariables()
{
// Set the Bus Speed (APB1 or APB2), all timers are APB1 except TIM1 and TIM8...
if (PWMPin == CPU.Pin.Pin7_X3 || PWMPin == CPU.Pin.Pin9_X3 || PWMPin == CPU.Pin.Pin7_X4)
{
ClockSpeed = CPU.Clock.APB2;
}
else
{
ClockSpeed = CPU.Clock.APB1;
}
#region Fields...
uint ONE_MHZ = 1000000;
uint prescaler = 0;
uint period = m_period;
uint duration = m_duration;
uint scale = ((uint)m_scale);
// Scale in MHz...
uint scaleMHz = scale / ONE_MHZ;
uint clk = ((uint)ClockSpeed / ONE_MHZ);
if (duration > period) duration = period;
#endregion
#region Calculate Variables (This is a C# implimentation of GHI Source ("PWM_ApplyConfiguration"))...
prescaler = clk / scale;
if (prescaler == 0)
{
if (period > (0xFFFFFFFF / clk))
{
// Avoid Overflow...
prescaler = clk;
period /= scaleMHz;
duration /= scaleMHz;
}
else
{
prescaler = 1;
period = period * clk / scaleMHz;
duration = duration * clk / scaleMHz;
}
}
else
{
while (prescaler > 0x10000)
{
// Prescaler too Large...
if (period >= 0x80000000) break;
prescaler >>= 1;
period <<= 1;
duration <<= 1;
}
}
bool TimerIs16Bit = true;
// Were not using Timer 2 of Timer 5...
if (TimerIs16Bit)
{
// All Timers are 16 bit Timer's except 2 and 5...
while (period >= 0x10000)
{
// period too large
if (prescaler > 0x8000) break;
prescaler <<= 1;
period >>= 1;
duration >>= 1;
}
}
#endregion
if (debug)
{
Debug.Print("*** Scale *******");
// Print to Debug window new config...
Debug.Print("Period = " + period);
Debug.Print("Prescaler = " + PrescalerFromPeriodFrequencyAndClock(period, this.Frequency));
Debug.Print("Duration = " + duration);
}
ARRValue = (period - 1);
PSCValue = PrescalerFromPeriodFrequencyAndClock(period, this.Frequency);
CCRxValue = duration;
}
a Simple static Class CPU and I have added:
public enum Pin : int
{
Pin7_X3 = 1,
Pin8_X3 = 2,
Pin9_X3 = 3,
Pin7_X4 = 4,
Pin8_X4 = 5,
Pin9_X4 = 6
}
Depending on the clock, prescaler and auto reload, repetition counter (if present) parameters, the 16-bit timer can generate an update event from a nanosecond to a few minutes.
For example, to generate an event two times per second, choose Clock frequency(TIM_CLK) = 168 Mhz, Prescalar(PSC) = 16799, Period(ARR) = 4999, repetition counter(RCR) = 0,
then the 16-bit timer will generate an event two times per second.
For more information ;
STM32 Timer Overview