[][src]Module stm32f3xx_hal::pwm

Pulse width modulation

Numerous stm32 timers can be used to output pulse width modulated signals on a variety of pins. The timers support up to 4 simultaneous pwm outputs in separate Channels. These channels share a period and resolution, but can have a different duty cycle. All pins on a shared channel have the exact same output.

Creating the (unconfigured) channels

Before we connect any pins, we need to convert our timer peripheral into a set of channels. We may only be interested in using one or two of these channels, so we can simply ignore them with _ when we destructure.

  // (Other imports omitted)
  use stm32f3xx-hal::pwm::tim3;

  let dp = stm32f303::Peripherals::take().unwrap();

  let mut flash = dp.FLASH.constrain();
  let mut rcc = dp.RCC.constrain();
  let clocks = rcc.cfgr.freeze(&mut flash.acr);

  // Set the resolution of our duty cycle to 9000 and our period to
  // 50hz.
  let mut (c1_no_pins, _, _, c4_no_pins) =
      tim3(device.TIM3, 9000, 50.hz(), clocks);

In this case, we're only going to use channel 1 and channel 4. Currently we can't enable these timers, because they don't have any pins, so the following wouldn't compile.

  // DOES NOT COMPILE
  c1_no_pins.enable();
  c4_no_pins.enable();

Connecting our pins and enabling the channels

From here we can connect as many compatible pins as we like. Once the channels have pins connected they can be enabled.

  let mut gpioa = dp.GPIOB.split(&mut rcc.ahb);
  let pa6 = gpioa.pa6.into_af2(&mut gpioa.moder, &mut gpioa.afrl);

  let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
  let pb1 = gpiob.pb1.into_af2(&mut gpiob.moder, &mut gpiob.afrl);
  let pb4 = gpiob.pb4.into_af2(&mut gpiob.moder, &mut gpiob.afrl);

  let mut ch1 = ch1_no_pins
      .output_to_pa6(pa6)
      .output_to_pb4(pb4);

  let mut ch4 = ch4_no_pins
      .output_to_pb1(pb1);

  ch1.enable();
  ch4.enable();

All three pins will output a 50hz period. PA6 and PB4 will share a duty cycle, but the duty cycle for PB1 can be controlled independently.

  // Affect PA6 and PB4
  ch1.set_duty_cycle(1000);

  // Affect only PB1
  ch4.set_duty_cycle(2000);

Single channel timers

Timers that only have only one channel do not return a tuple, and instead return the (unconfigured) channel directly.

  // (Other imports omitted)
  use stm32f3xx-hal::pwm::tim16;

  let dp = stm32f303::Peripherals::take().unwrap();

  let mut flash = dp.FLASH.constrain();
  let mut rcc = dp.RCC.constrain();
  let clocks = rcc.cfgr.freeze(&mut flash.acr);

  // Set the resolution of our duty cycle to 9000 and our period to
  // 50hz.
  let mut c1_no_pins = tim16(device.TIM3, 9000, 50.hz(), clocks);

Complementary timers

Certain timers have complementary outputs. Currently, channels can output to either pins used for standard or complementary pins (and do not exhibit complementary behaviors). Most of the time this will be totally invisible.

In this example, we use a complementary pin in the same way we'd use any other pwm channel.

  // (Other imports omitted)
  use stm32f3xx-hal::pwm::tim1;

  let dp = stm32f303::Peripherals::take().unwrap();

  let mut flash = dp.FLASH.constrain();
  let mut rcc = dp.RCC.constrain();
  let clocks = rcc.cfgr.freeze(&mut flash.acr);

  // Set the resolution of our duty cycle to 9000 and our period to
  // 50hz.
  let mut (ch1_no_pins, _, _, _) = tim1(device.TIM3, 9000, 50.hz(), clocks);

  let mut gpioa = dp.GPIOB.split(&mut rcc.ahb);
  let pa7 = gpioa.pa7.into_af6(&mut gpioa.moder, &mut gpioa.afrl);

  let mut ch1 = ch1_no_pins.output_to(pa7);
  ch1.enable();

We used this channel/pin exactly like any previous example.

However, we cannot use standard and complementary pins simultaneously. Luckily, typestates enforce this for us.

  ...

  let mut gpioa = dp.GPIOB.split(&mut rcc.ahb);
  let pa7 = gpioa.pa7.into_af6(&mut gpioa.moder, &mut gpioa.afrl);
  let pa8 = gpioa.pa8.into_af6(&mut gpioa.moder, &mut gpioa.afrl);

  let mut ch1 = ch1_no_pins
      .output_to(pa7)
      // DOES NOT COMPILE
      .output_to(pa8);

Once we've connected a complementary pin (PA7) we are now only allowed to use other complementary pins. PA8 is a valid choice if we have no pins in use, but it cannot be used once we've used PA7.

Structs

NoPins

Type state used to represent a channel that has no pins yet

PwmChannel

Representation of a Channel for an abritary timer channel, that also holds a type state for whether or not this channel is using any pins yet.

TIM15_CH1

Output Compare Channel 1 of Timer 15 (type state)

TIM15_CH2

Output Compare Channel 2 of Timer 15 (type state)

TIM16_CH1

Output Compare Channel 1 of Timer 16 (type state)

TIM17_CH1

Output Compare Channel 1 of Timer 17 (type state)

TIM1_CH1

Output Compare Channel 1 of Timer 1 (type state)

TIM1_CH2

Output Compare Channel 2 of Timer 1 (type state)

TIM1_CH3

Output Compare Channel 3 of Timer 1 (type state)

TIM1_CH4

Output Compare Channel 4 of Timer 1 (type state)

TIM2_CH1

Output Compare Channel 1 of Timer 1 (type state)

TIM2_CH2

Output Compare Channel 2 of Timer 1 (type state)

TIM2_CH3

Output Compare Channel 3 of Timer 1 (type state)

TIM2_CH4

Output Compare Channel 4 of Timer 1 (type state)

TIM3_CH1

Output Compare Channel 1 of Timer 3 (type state)

TIM3_CH2

Output Compare Channel 2 of Timer 3 (type state)

TIM3_CH3

Output Compare Channel 3 of Timer 3 (type state)

TIM3_CH4

Output Compare Channel 4 of Timer 3 (type state)

TIM4_CH1

Output Compare Channel 1 of Timer 4 (type state)

TIM4_CH2

Output Compare Channel 2 of Timer 4 (type state)

TIM4_CH3

Output Compare Channel 3 of Timer 4 (type state)

TIM4_CH4

Output Compare Channel 4 of Timer 4 (type state)

TIM8_CH1

Output Compare Channel 1 of Timer 8 (type state)

TIM8_CH2

Output Compare Channel 2 of Timer 8 (type state)

TIM8_CH3

Output Compare Channel 3 of Timer 8 (type state)

TIM8_CH4

Output Compare Channel 4 of Timer 8 (type state)

WithNPins

Type state used to represent a channel is using (only) complementary pins

WithPins

Type state used to represent a channel is using regular pins

Functions

tim1

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim2

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim3

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim4

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim8

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim15

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim16

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.

tim17

Create one or more output channels from a TIM Peripheral This function requires the maximum resolution of the duty cycle, the period of the PWM signal and the frozen clock configuration.