diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index bd8358563..674740cc5 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs @@ -55,6 +55,9 @@ pub(crate) mod sealed { use super::*; pub trait CaptureCompare16bitInstance: crate::timer::sealed::Basic16bitInstance { + /// Global output enable. Does not do anything on non-advanced timers. + unsafe fn enable_outputs(&mut self, enable: bool); + unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); @@ -88,6 +91,8 @@ pub trait CaptureCompare32bitInstance: macro_rules! impl_compare_capable_16bit { ($inst:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + unsafe fn enable_outputs(&mut self, _enable: bool) {} + unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { use crate::timer::sealed::GeneralPurpose16bitInstance; let r = Self::regs_gp16(); @@ -118,38 +123,7 @@ macro_rules! impl_compare_capable_16bit { foreach_interrupt! { ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn set_output_compare_mode( - &mut self, - channel: crate::pwm::Channel, - mode: OutputCompareMode, - ) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - let r = Self::regs_gp16(); - let raw_channel: usize = channel.raw(); - r.ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .ccer() - .modify(|w| w.set_cce(channel.raw(), enable)); - } - - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .ccr(channel.raw()) - .modify(|w| w.set_ccr(value)); - } - - unsafe fn get_max_compare_value(&self) -> u16 { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().arr().read().arr() - } - } + impl_compare_capable_16bit!($inst); impl CaptureCompare16bitInstance for crate::peripherals::$inst { @@ -194,6 +168,12 @@ foreach_interrupt! { ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + unsafe fn enable_outputs(&mut self, enable: bool) { + use crate::timer::sealed::AdvancedControlInstance; + let r = Self::regs_advanced(); + r.bdtr().modify(|w| w.set_moe(enable)); + } + unsafe fn set_output_compare_mode( &mut self, channel: crate::pwm::Channel, diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index a475f3f70..049a64027 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/pwm/simple_pwm.rs @@ -92,6 +92,8 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { this.inner.start(); unsafe { + this.inner.enable_outputs(true); + this.inner .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); this.inner diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs new file mode 100644 index 000000000..cd20c68bb --- /dev/null +++ b/examples/stm32f4/src/bin/pwm.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy::executor::Spawner; +use embassy::time::{Duration, Timer}; +use embassy_stm32::pwm::simple_pwm::SimplePwm; +use embassy_stm32::pwm::Channel; +use embassy_stm32::time::U32Ext; +use embassy_stm32::Peripherals; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy::main] +async fn main(_spawner: Spawner, p: Peripherals) { + info!("Hello World!"); + + let mut pwm = SimplePwm::new_1ch(p.TIM1, p.PE9, 10000.hz()); + let max = pwm.get_max_duty(); + pwm.enable(Channel::Ch1); + + info!("PWM initialized"); + info!("PWM max duty {}", max); + + loop { + pwm.set_duty(Channel::Ch1, 0); + Timer::after(Duration::from_millis(300)).await; + pwm.set_duty(Channel::Ch1, max / 4); + Timer::after(Duration::from_millis(300)).await; + pwm.set_duty(Channel::Ch1, max / 2); + Timer::after(Duration::from_millis(300)).await; + pwm.set_duty(Channel::Ch1, max - 1); + Timer::after(Duration::from_millis(300)).await; + } +}