Hardware Reference
In-Depth Information
pwm Program
The program software
pwm
is listed at the end of this chapter. To facilitate discussion,
I'll show excerpts of it here. The hardware example driven by
pwm.c
is the nastier of the
two programs presented. This is due to the difficulty of programming the PWM hardware
registers and the clock-rate registers.
The main program invokes
pwm_init()
, which gains access to the Pi's peripherals
in much the same way that the other examples did in
gpio_init()
. The same
mmap()
techniques are used for access to the PWM and CLK control registers.
Whether operating
pwm
to just set the PWM peripheral or to use the CPU percent-busy
function, the PWM frequency must be set by the function
pwm_frequency()
:
static int
pwm_frequency(float freq) {
...
This function stops the clock that is running and computes a new integer divisor.
After disabling the clock, a little sleep time is used to allow the clock peripheral to stop.
The maximum clock rate appears to be 19.2 MHz. To compute the divisor, the following
calculation is used:
div
=
19200000
I
f
where:
•
I
div
is the computed integer divisor.
•
f
is the desired PWM frequency.
The range of the resulting
I
div
is checked against the peripheral's limits. The value
of
I
div
is then forced to remain in range, but the return value is
-1
or
+1
depending on
whether the frequency is under or over the limits.
idiv = (long)( clock_rate / (double) freq );
if ( idiv < 1 ) {
idiv = 1; /* Lowest divisor */
rc = -1;
} else if ( idiv >= 0x1000 ) {
idiv = 0xFFF; /* Highest divisor */
rc = +1;
}
Once that is calculated, the value of
I
div
is loaded:
ugclk[PWMCLK_DIV] = 0x5A000000 | ( idiv << 12 );