Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PWM Peripheral in RP2040

The RP2040 has a PWM peripheral with 8 PWM generators called slices. Each slice contains two output channels (A and B), giving you a total of 16 PWM output channels at the slice level, which can be routed to GPIO pins. For detailed specifications, see page 521 of the RP2040 Datasheet.

Let’s have a quick look at some of the key concepts.

PWM Generator (Slice)

A slice is the hardware block that generates PWM signals. Each of the 8 slices (PWM0-PWM7) is an independent timing unit with its own 16-bit counter, compare registers, control settings, and clock divider. This independence means you can configure each slice with different frequencies and resolutions.

Channel

Each slice contains two output channels: Channel A and Channel B. Both channels share the same counter, so they run at the same frequency and are synchronized. However, each channel has its own compare register, allowing independent duty cycle control. This lets you generate two related but distinct PWM signals from a single slice.

Mapping of PWM channels to GPIO Pins

Each GPIO pin connects to a specific slice and channel, and the same slice output can be routed to more than one GPIO pin. You’ll find the complete mapping table on page 522 of the RP2040 Datasheet. For example, GPIO Pin 15 to PWM slice 7, channel B, labeled as 7B.

pico

Initialize PWM

You create a PWM output by binding a specific PWM slice, channel, and GPIO pin at construction time. For example, GPIO pin 15 maps to PWM slice 7, channel B. You can create a PWM output for this pin using Pwm::new_output_b, which selects the slice, channel, and output pin in a single step.

#![allow(unused)]
fn main() {
let mut pwm = Pwm::new_output_b(p.PWM_SLICE7, p.PIN_15, Default::default());
}

GPIO to PWM

I have created a small form that helps you figure out which GPIO pin maps to which PWM channel and also generates sample code.

Select a GPIO pin to see PWM mapping and generated code.

Phase-Correct Mode

In standard PWM (fast PWM), the counter counts up from 0 to TOP, then immediately resets to 0. This creates asymmetric edges where the output changes at different points in the cycle.

Phase-correct PWM counts up to TOP, then counts back down to 0, creating a triangular waveform. The output switches symmetrically - once going up and once coming down. This produces centered pulses with edges that mirror each other, reducing electromagnetic interference and creating smoother transitions. The trade-off is that, with the same clock divider and TOP value, phase-correct mode runs at half the frequency of standard PWM.

Configure PWM slice 7 to operate in phase-correct mode for smoother output transitions.

#![allow(unused)]
fn main() {
pwm.set_phase_correct(true);
}