Raspberry Pi CM5 IoT In C - - PWM Using GPIO5
Written by Harry Fairhead   
Monday, 12 May 2025
Article Index
Raspberry Pi CM5 IoT In C - - PWM Using GPIO5
Pulse Density Mode
The PWM Registers
Working with PWM
What Else Can You Use PWM For?

Pulse Density Mode

Simple PWM isn’t so good for some power control tasks because the frequency is often low. This makes the filtering problem and hence creating a smooth output voltage, more difficult. For example, suppose you want a 1kHz pulse train with a 50% duty cycle to deliver half power or voltage to a device. The mark/space way of doing this switches the GPIO line on for 500µs and off for 500µs. The fluctuations in voltage are very slow and this causes problems for the driven device.

A better way would be to spread the high time across all of the clock cycles. For example, if the clock is 1µs then instead of setting the line high for the first 500 clock pulses and then low for the final 500 clock pulses it might be better to distribute 500 high clock pulses throughout the 1000 clock pulses:

blocks and spread the on and off times throughout the block to give the overall desired duty cycle. In this case the device would be high for 1µs and low for 1µs and the filtering problems would be much easier to solve.

You can see this for a lower clock rate in the diagram below. The top figure shows a standard PWM 50% duty cycle and the bottom image shows the same duty cycle spread across the entire repeat period:

The algorithm for achieving the distribution of the "high" time across the full range period is given in the ARM manual as:

context = 0;
for(i=0;i<range;i++) {
 	context = context + data;
 	if(context >= range){
  		context = context - range;
  		set line high
	}else{
set line low
}

Suppose Range is 8 and Duty is 4, giving a 50% duty cycle, then the algorithm generates:

clock             1  2  3  4  5  6  7  8
context           4  8  4  8  4  8  4  8 
line              0  1  0  1  0  1  0  1
mark/space mode   1  1  1  1  0  0  0  0

Notice that each output pulse is the same width as the clock time rather than the time to count up to Range.

Pulse Position Mode

In pulse position mode the counter runs from 0 to Range and the output is only high when the count equals Duty. In this case the output is a single pulse, the width of the clock, at a position determined by Duty. That is, changing Duty changes where the pulse occurs.

There are also two serializer modes which allow you to output an arbitrary pulse train. Both modes make use of the duty register as a shift register and the output is composed of either the most significant, Serializer_MSB, or least significant, Serializer_LSB. bit in the shift register.

To summarize:

  • There are three “proper” PWM modes – leading-edge, trailing-edge and double-edge mode which only differ in the phase of the signal they generate.

  • The value of Range and the clock frequency set the PWM frequency.

  • In the proper PWM modes, duty sets the time that the output is high for each PWM cycle.

  • The pulse density and pulse position modes generate pulses that are the width of the clock pulse and vary in density or position based on the value of Duty.

  • The serializer modes let you send a 32-bit bit stream stored in Duty as the output of the PWM.

In addition to these modes, the PWM channels can be configured to share a common range and duty register. There is also a shared 32-bit FIFO register, a “first-in, first out” queue with storage for 128 32-bit values that can be used to set the duty of enabled channels.

Notice that all four of the PWM channels are fed by a single clock which can be set to a frequency via a programmable divider. The only way that the PWM channels can produce different frequencies is by having different values of range.

Clocks and Duty Cycle Resolution

If you just take the PWM driver at face value then you might believe that you can set any frequency and any duty cycle – this is not the case. Due to hardware limitations, the resolution of the duty cycle depends on the PWM clock frequency and this also governs the highest frequency PWM signal you can create. 25MHz


The PWM clock is set to 50MHz and the PWM signal can only change once per clock pulse. What this means is that the highest frequency that you can use is 25MHz with a 50% duty cycle:

What happens is that two clock pulses are needed to change the state of the line twice – once high and once low. This corresponds to range=1 and duty=1. You can also see that 50% is the only possible duty cycle apart from 0% and 100%.

The number of different duty cycles you can achieve depends on the number of clock pulses in the total PWM period.

You can easily work out the number of duty cycles available at any given frequency:

PWM Frequency

Number of clock pulses

Number of different duty cycles

Resolution in bits

25MHz

2

3

1.6

12.5MHz

4

5

2.3

6.25MHz

8

9

3.2

3.125MHz

16

17

4.1

781kHz

32

33

5.0

390kHz

64

65

6.0

195kHz

128

129

7.0

nkHz

50000/n

50000/n + 1

Log2(50000/n +1)

 

In many applications 8-bit resolution for the duty cycle is considered the minimum acceptable and this sets the highest frequency to about 195kHz, which is high enough for most things. For example, if you want to control a servo motor, see later, then you need a PWM signal with a frequency of 50Hz and at this frequency you can specify the duty cycle down to about 25 bits or around 40 million increments, more than enough for any real servo motor.



Last Updated ( Tuesday, 13 May 2025 )