diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 4f033e3a2..0ab727344 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -122,6 +122,46 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
     }
 }
 
+impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
+    type Channel = Channel;
+    type Time = Hertz;
+    type Duty = u16;
+
+    fn disable(&mut self, channel: Self::Channel) {
+        self.inner.enable_complementary_channel(channel, false);
+        self.inner.enable_channel(channel, false);
+    }
+
+    fn enable(&mut self, channel: Self::Channel) {
+        self.inner.enable_channel(channel, true);
+        self.inner.enable_complementary_channel(channel, true);
+    }
+
+    fn get_period(&self) -> Self::Time {
+        self.inner.get_frequency().into()
+    }
+
+    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
+        self.inner.get_compare_value(channel)
+    }
+
+    fn get_max_duty(&self) -> Self::Duty {
+        self.inner.get_max_compare_value() + 1
+    }
+
+    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
+        assert!(duty <= self.get_max_duty());
+        self.inner.set_compare_value(channel, duty)
+    }
+
+    fn set_period<P>(&mut self, period: P)
+    where
+        P: Into<Self::Time>,
+    {
+        self.inner.set_frequency(period.into());
+    }
+}
+
 fn compute_dead_time_value(value: u16) -> (Ckd, u8) {
     /*
         Dead-time = T_clk * T_dts * T_dtg
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index d88fbcfdb..1e0999ed3 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -70,6 +70,16 @@ pub(crate) mod sealed {
         fn set_autoreload_preload(&mut self, enable: vals::Arpe) {
             Self::regs().cr1().modify(|r| r.set_arpe(enable));
         }
+
+        fn get_frequency(&self) -> Hertz {
+            let timer_f = Self::frequency();
+
+            let regs = Self::regs();
+            let arr = regs.arr().read().arr();
+            let psc = regs.psc().read().psc();
+
+            timer_f / arr / (psc + 1)
+        }
     }
 
     pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
@@ -103,6 +113,16 @@ pub(crate) mod sealed {
             regs.egr().write(|r| r.set_ug(true));
             regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
         }
+
+        fn get_frequency(&self) -> Hertz {
+            let timer_f = Self::frequency();
+
+            let regs = Self::regs_gp32();
+            let arr = regs.arr().read().arr();
+            let psc = regs.psc().read().psc();
+
+            timer_f / arr / (psc + 1)
+        }
     }
 
     pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
@@ -183,6 +203,10 @@ pub(crate) mod sealed {
         fn get_max_compare_value(&self) -> u16 {
             Self::regs_gp16().arr().read().arr()
         }
+
+        fn get_compare_value(&self, channel: Channel) -> u16 {
+            Self::regs_gp16().ccr(channel.raw()).read().ccr()
+        }
     }
 
     pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
@@ -219,6 +243,10 @@ pub(crate) mod sealed {
         fn get_max_compare_value(&self) -> u32 {
             Self::regs_gp32().arr().read().arr()
         }
+
+        fn get_compare_value(&self, channel: Channel) -> u32 {
+            Self::regs_gp32().ccr(channel.raw()).read().ccr()
+        }
     }
 }
 
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 9e28878b1..2b3a069a7 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -109,3 +109,41 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
         self.inner.set_output_polarity(channel, polarity);
     }
 }
+
+impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
+    type Channel = Channel;
+    type Time = Hertz;
+    type Duty = u16;
+
+    fn disable(&mut self, channel: Self::Channel) {
+        self.inner.enable_channel(channel, false);
+    }
+
+    fn enable(&mut self, channel: Self::Channel) {
+        self.inner.enable_channel(channel, true);
+    }
+
+    fn get_period(&self) -> Self::Time {
+        self.inner.get_frequency().into()
+    }
+
+    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
+        self.inner.get_compare_value(channel)
+    }
+
+    fn get_max_duty(&self) -> Self::Duty {
+        self.inner.get_max_compare_value() + 1
+    }
+
+    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
+        assert!(duty <= self.get_max_duty());
+        self.inner.set_compare_value(channel, duty)
+    }
+
+    fn set_period<P>(&mut self, period: P)
+    where
+        P: Into<Self::Time>,
+    {
+        self.inner.set_frequency(period.into());
+    }
+}