I found this PWM frequency note with frequency formula. Hope this helps
We have recently received several questions about the range of frequencies available with the PWM feature of the Rabbit processors. This article will review programming the PWM features and, in doing so, show the limits of the PWM parameters.
Several customers have asked “How can I get a PWM frequency of 50Hz from my Rabbit?” My response to this question is something like the following:
I need to know which Rabbit product you are using before I can answer your question. However, here is the formula you can use to determine the frequency range available
(1) Frequency = FCPU/1024/(TAT9R+1)/2
The reasons for the various divisors are:
• The factor of 1024 is because the PWM system has 10 bit resolution. One output period is divided into 1024 time slots with the “on” time being programmable via PWM registers.
• Timer A9 is used to drive the PWM counter and it divides by N+1
• The default for all Rabbit processors is that the Peripheral Clock/2 (Pclk/2) drives each of the Timers in the Timer A group and that Pclk is the same frequency as FCPU.
Given this formula and knowing the FCPU for your Rabbit you can now calculate the basic PWM frequency range. For example – using an RCM5700 with a clock of 50MHz the range of PWM frequencies can be calculated as follows:
(2) FCPU/1024/(255+1)/2 <= PWM <= FCPU/1024/(0+1)/2 which reduces to…
(3) 50MHz/524288 <= PWM <= 50MHz/2048 which reduces to…
(4) 95.4Hz <= PWM <= 24414Hz
There are two other features of the PWM system which can be useful in certain situations. One is the ability it has to “swallow” 1of 2, 3 of 4 or 7 of 8 pulses. This reduces the frequency by a factor of 2, 4 or 8 but the available pulse width is still based on the original frequency. For instance, if the 1 of 2 option is chosen, the maximum effective pulse width available will be 50%. This feature is useful for those applications which require a very low duty cycle but still maintain high resolution. The servo motors in Radio Control models is one example.
The other feature is that of Pulse Spreading. When this feature is enabled the system will output four pulses, evenly spaced across the period, instead of a single pulse. Each of the four pulses will be 1/4th the width of the equivalent single pulse output. This output could be more easily filtered by whatever load the PWM system is driving. Enabling this feature has the side effect of multiplying the output frequency by a factor of four. However, this effectively reduces the PWM resolution to 8 bits.
If you require lower PWM frequencies and you can tolerate a slower CPU clock then one easy way to achieve this is to reduce the CPU clock frequency. Rabbits allow you to control the main clock frequency in two ways:
1. Turn off the clock doubler
2. Divide the CPU clock by integer values using GCSR. The Rabbit 2000 allows you to divide by 8 while the newer ones allow ratios of 2, 4, 6 and 8.
Keep in mind that doing this affects all the systems within the Rabbit including the serial port baud rates.
Another possible solution which works on the Rabbit 4000 and 5000 processors is to use Timer C to generate PWM. It has a 16 bit counter and can be driven Pclk/2 (the default), Pclk/16 or Timer A1. This yields a much larger range of output frequencies than is available for the PWM system. The formula for the output frequency is:
(5) Frequency = InputFrequency/(M+1) where 0 <= M <= 65535.
The way a Timer C output works is that it can be set and reset by any value within the range 0 to M. For example, the PWM feature can be emulated by selecting Pclk/2 as the input, setting M to 1023, the set count to 0 and the reset count to any value between 0 and 1023 inclusive. Using an RCM5700 again the output frequency will be:
(6) 50MHz/2/1024 = 24414Hz
If Timer A1 is selected as the frequency source for Timer C and TAT1R is set to 255 the output frequency is:
(7) 50MHz/1024/(255+1)/2 = 95.4Hz
Note that this is the same frequency range as is available with the PWM system and the resolution will be the same as well.
Using the capability of Timer C we can adjust the frequency using the main divider without having to use Timer A1. If M in equation (5) is set to 65535 and Timer C is driven by Pclk/2 the output frequency will be 381.5Hz and the PWM resolution will be 1 part in 65536. Driving Timer C with Pclk/16 will yield a lower frequency limit of 47.7Hz.
With Timer C we can do the calculation in reverse to determine what divider is required for a specific frequency by solving equation (5) for M:
M = (InputFrequency – OutputFrequency)/ OutputFrequency.
For example if an output frequency of 50Hz is needed and Pclk/16 is the input frequency then:
(9) M = ( Pclk/16 – 50)/50 = 62499
Obviously, this will work since this value is less than 65535. However, in order to demonstrate a more general case let’s see what is needed to generate a 30Hz signal. The value of M would need to be 104166. This is obviously not within the range of a 16 bit value.
So, it looks like we need to use timer A1 as a prescaler. Since it is driven by Pclk/2 we can start with TAT1R set to 15 and see how the numbers work out. The divisor is 16 since TAT1R divides by N+1. In this case:
(10) M = (Pclk/2/16 – 30 ) / 30 = (50MHz/32 – 30 ) / 30 = 52082.3
This is within the 16 bit range of the Timer C divider. You will need to decide whether you want a slightly higher (M=52082) frequency or slightly lower (M=52083) frequency. There are quite a few values for TAT1R which will allow you to achieve results close to 30Hz. There are probably some values which will yield exactly 30Hz but I will leave that search to those who need it.
Now all you need to do is set the percentage of on-time by multiplying the value of M by the percentage/100. For instance if you want a 35% duty cycle:
(11) TCRX = 0.35 * M
Where TCRX is the 16 bit value that must be programmed in to the appropriate Timer C Reset Register pair. This assumes that TCSX is set to 0 so that the pulse turns on at a count of 0. If you need to offset the pulse by setting a non-zero value into TCSX then:
(12) TCRX = TCSX + (0.35 * M)
There is a sample program which demonstrates most of the features and formulae discussed in this article: AskLarry_PWM.c.