Expand description

Pulse Width Modulation (PWM)

First you must create a Slices struct which contains all the pwm slices.

use rp2040_hal::{prelude::*, pwm::{InputHighRunning, Slices}};


let mut pac = rp2040_pac::Peripherals::take().unwrap();

// Init PWMs
let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);

// Configure PWM4
let mut pwm = pwm_slices.pwm4;
pwm.set_ph_correct();
pwm.enable();

// Set to run when b channel is high
let pwm  = pwm.into_mode::<InputHighRunning>();

Once you have the PWM slice struct, you can add individual pins:

use embedded_hal::PwmPin;

// Use B channel (which inputs from GPIO 25)
let mut channel_b = pwm.channel_b;
let channel_pin_b = channel_b.input_from(pins.gpio25);

// Use A channel (which outputs to GPIO 24)
let mut channel_a = pwm.channel_a;
let channel_pin_a = channel_a.output_to(pins.gpio24);

// Set duty cycle
channel_a.set_duty(0x00ff);
channel_a.get_duty();
channel_a.set_inverted(); // Invert the output
channel_a.clr_inverted(); // Don't invert the output

The following configuration options are also available:

pwm.set_ph_correct(); // Run in phase correct mode
pwm.clr_ph_correct(); // Don't run in phase correct mode

pwm.set_div_int(1u8); // To set integer part of clock divider
pwm.set_div_frac(0u8); // To set fractional part of clock divider

pwm.get_top(); // To get the TOP register
pwm.set_top(u16::MAX); // To set the TOP register

default_config() sets ph_correct to false, the clock divider to 1, does not invert the output, sets top to 65535, and resets the counter. min_config() leaves those registers in the state they were before it was called (Careful, this can lead to unexpected behavior) It’s recommended to only call min_config() after calling default_config() on a pin that shares a PWM block.

Re-exports

pub use dyn_slice::*;

Modules

Semi-internal enums mostly used in typelevel magic

Structs

A Channel from the Pwm subsystem.

Count once with each falling edge detected on the B pin

Count once with each rising edge detected on the B pin

Counter is free-running, and will count continuously whenever the slice is enabled

Count continuously when a high level is detected on the B pin

Stores the attached gpio pin.

Pwm slice

Collection of all the individual Slicess

Enums

Channel A

Channel B

Slice ID representing slice 0

Slice ID representing slice 1

Slice ID representing slice 2

Slice ID representing slice 3

Slice ID representing slice 4

Slice ID representing slice 5

Slice ID representing slice 6

Slice ID representing slice 7

Traits

Used to pin traits to a specific channel (A or B)

Make sure we can’t free an GPIO pin while still keeping it attached to pwm TODO: Maybe FunctionPWM should be private?

Type-level enum for slice IDs

Mode for slice

Marker trait for valid output pins

Marker trait for valid input pins (Channel B only)

Type-level marker for tracking which slice modes are valid for which slices

Type-level marker for tracking which slice modes are valid for which slices