[−][src]Module stm32f1xx_hal::pwm
Pulse width modulation
The general purpose timers (TIM2
, TIM3
, and TIM4
) can be used to output
pulse width modulated signals on some pins. The timers support up to 4
simultaneous pwm outputs in separate Channels
Usage for pre-defined channel combinations
This crate only defines basic channel combinations for default AFIO remappings, where all the channels are enabled. Start by setting all the pins for the timer you want to use to alternate push pull pins:
let gpioa = ..; // Set up and split GPIOA let pins = ( gpioa.pa0.into_alternate_push_pull(), gpioa.pa1.into_alternate_push_pull(), gpioa.pa2.into_alternate_push_pull(), gpioa.pa3.into_alternate_push_pull(), );
Then call the pwm
function on the corresponding timer:
let device: pac::Peripherals = ..; // Put the timer in PWM mode using the specified pins // with a frequency of 100 hz. let (c0, c1, c2, c3) = device.TIM2.pwm( pins, &mut afio.mapr, 100.hz(), clocks, &mut rcc.apb1 ); // Set the duty cycle of channel 0 to 50% c0.set_duty(c0.get_max_duty() / 2); // PWM outputs are disabled by default c0.enable()
Usage for custom channel combinations
Note that crate itself defines only basic channel combinations for default AFIO remappings,
where all the channels are enabled. Meanwhile it is possible to configure PWM for any custom
selection of channels. The Pins
trait shows the mapping between timers, output pins and
channels. So this trait needs to be implemented for the custom combination of channels and
AFIO remappings. However minor additional efforts are needed since it is not possible to
implement a foreign trait for a foreign type. The trick is to use the newtype pattern.
The first example selects PB5 channel for TIM3 PWM output:
struct MyChannels(PB5<Alternate<PushPull>>); impl Pins<TIM3> for MyChannels { const REMAP: u8 = 0b10; // use TIM3 AFIO remapping for PB4, PB5, PB0, PB1 pins const C1: bool = false; const C2: bool = true; // use channel C2 const C3: bool = false; const C4: bool = false; type Channels = Pwm<TIM3, C2>; }
The second example selects PC8 and PC9 channels for TIM3 PWM output:
struct MyChannels(PC8<Alternate<PushPull>>, PC9<Alternate<PushPull>>); impl Pins<TIM3> for MyChannels { const REMAP: u8 = 0b11; // use TIM3 AFIO remapping for PC6, PC7, PC8, PC9 pins const C1: bool = false; const C2: bool = false; const C3: bool = true; // use channel C3 const C4: bool = true; // use channel C4 type Channels = (Pwm<TIM3, C3>, Pwm<TIM3, C4>); }
REMAP value and channel pins should be specified according to the stm32f1xx specification, e.g. the section 9.3.7 "Timer alternate function remapping" in RM0008 Rev 20.
Finally, here is a complete example for two channels:
use stm32f1xx_hal::stm32::TIM3; use stm32f1xx_hal::gpio::gpiob::{PB4, PB5}; use stm32f1xx_hal::gpio::{Alternate, PushPull}; use stm32f1xx_hal::pwm::{Pins, Pwm, C1, C2, C3, C4}; struct MyChannels(PB4<Alternate<PushPull>>, PB5<Alternate<PushPull>>); impl Pins<TIM3> for MyChannels { const REMAP: u8 = 0b10; const C1: bool = true; const C2: bool = true; const C3: bool = false; const C4: bool = false; type Channels = (Pwm<TIM3, C1>, Pwm<TIM3, C2>) } ... let gpiob = ..; // Set up and split GPIOB let p1 = gpiob.pb4.into_alternate_push_pull(&mut gpiob.crl); let p2 = gpiob.pb5.into_alternate_push_pull(&mut gpiob.crl); ... let device: pac::Peripherals = ..; let (mut c1, mut c2) = device.TIM3.pwm( MyChannels(p1, p2), &mut afio.mapr, 100.hz(), clocks, &mut rcc.apb1 ); // Set the duty cycle of channels C1 and C2 to 50% and 25% respectively c1.set_duty(c1.get_max_duty() / 2); c2.set_duty(c2.get_max_duty() / 4); // PWM outputs are disabled by default c1.enable() c2.enable()
Structs
C1 | |
C2 | |
C3 | |
C4 | |
Pwm |
Traits
Pins | |
PwmExt |