diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 51b4b5fcc..b273c6394 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -10,7 +10,7 @@
 #[cfg_attr(adc_v1, path = "v1.rs")]
 #[cfg_attr(adc_l0, path = "v1.rs")]
 #[cfg_attr(adc_v2, path = "v2.rs")]
-#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
+#[cfg_attr(any(adc_v3, adc_g0, adc_h5), path = "v3.rs")]
 #[cfg_attr(adc_v4, path = "v4.rs")]
 mod _version;
 
@@ -79,10 +79,10 @@ pub(crate) mod sealed {
 }
 
 /// ADC instance.
-#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
+#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))]
 pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
 /// ADC instance.
-#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
+#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))]
 pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
 
 /// ADC pin.
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs
index 0e6c45c65..37788cd77 100644
--- a/embassy-stm32/src/adc/resolution.rs
+++ b/embassy-stm32/src/adc/resolution.rs
@@ -1,6 +1,6 @@
 /// ADC resolution
 #[allow(missing_docs)]
-#[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
+#[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub enum Resolution {
@@ -25,7 +25,7 @@ pub enum Resolution {
 
 impl Default for Resolution {
     fn default() -> Self {
-        #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
+        #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))]
         {
             Self::TwelveBit
         }
@@ -46,7 +46,7 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
             Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
             Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
             Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
-            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
+            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))]
             Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
         }
     }
@@ -65,7 +65,7 @@ impl Resolution {
             Resolution::TwelveBit => (1 << 12) - 1,
             Resolution::TenBit => (1 << 10) - 1,
             Resolution::EightBit => (1 << 8) - 1,
-            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
+            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))]
             Resolution::SixBit => (1 << 6) - 1,
         }
     }
diff --git a/embassy-stm32/src/adc/sample_time.rs b/embassy-stm32/src/adc/sample_time.rs
index f4b22b462..19bc22938 100644
--- a/embassy-stm32/src/adc/sample_time.rs
+++ b/embassy-stm32/src/adc/sample_time.rs
@@ -67,7 +67,7 @@ impl_sample_time!(
     )
 );
 
-#[cfg(adc_v3)]
+#[cfg(any(adc_v3, adc_h5))]
 impl_sample_time!(
     "2.5",
     Cycles2_5,
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 281a99f72..0c44e4400 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,3 +1,4 @@
+use cfg_if::cfg_if;
 use embassy_hal_internal::into_ref;
 use embedded_hal_02::blocking::delay::DelayUs;
 
@@ -13,10 +14,15 @@ pub struct VrefInt;
 impl<T: Instance> AdcPin<T> for VrefInt {}
 impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
     fn channel(&self) -> u8 {
-        #[cfg(not(adc_g0))]
-        let val = 0;
-        #[cfg(adc_g0)]
-        let val = 13;
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                let val = 13;
+            } else if #[cfg(adc_h5)] {
+                let val = 17;
+            } else {
+                let val = 0;
+            }
+        }
         val
     }
 }
@@ -25,10 +31,15 @@ pub struct Temperature;
 impl<T: Instance> AdcPin<T> for Temperature {}
 impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
     fn channel(&self) -> u8 {
-        #[cfg(not(adc_g0))]
-        let val = 17;
-        #[cfg(adc_g0)]
-        let val = 12;
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                let val = 12;
+            } else if #[cfg(adc_h5)] {
+                let val = 16;
+            } else {
+                let val = 17;
+            }
+        }
         val
     }
 }
@@ -37,14 +48,31 @@ pub struct Vbat;
 impl<T: Instance> AdcPin<T> for Vbat {}
 impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
     fn channel(&self) -> u8 {
-        #[cfg(not(adc_g0))]
-        let val = 18;
-        #[cfg(adc_g0)]
-        let val = 14;
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                let val = 14;
+            } else if #[cfg(adc_h5)] {
+                let val = 2;
+            } else {
+                let val = 18;
+            }
+        }
         val
     }
 }
 
+cfg_if! {
+    if #[cfg(adc_h5)] {
+        pub struct VddCore;
+        impl<T: Instance> AdcPin<T> for VddCore {}
+        impl<T: Instance> super::sealed::AdcPin<T> for VddCore {
+            fn channel(&self) -> u8 {
+                6
+            }
+        }
+    }
+}
+
 impl<'d, T: Instance> Adc<'d, T> {
     pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
         into_ref!(adc);
@@ -98,27 +126,41 @@ impl<'d, T: Instance> Adc<'d, T> {
     }
 
     pub fn enable_temperature(&self) -> Temperature {
-        #[cfg(not(adc_g0))]
-        T::common_regs().ccr().modify(|reg| {
-            reg.set_ch17sel(true);
-        });
-        #[cfg(adc_g0)]
-        T::regs().ccr().modify(|reg| {
-            reg.set_tsen(true);
-        });
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                T::regs().ccr().modify(|reg| {
+                    reg.set_tsen(true);
+                });
+            } else if #[cfg(adc_h5)] {
+                T::common_regs().ccr().modify(|reg| {
+                    reg.set_tsen(true);
+                });
+            } else {
+                T::common_regs().ccr().modify(|reg| {
+                    reg.set_ch17sel(true);
+                });
+            }
+        }
 
         Temperature {}
     }
 
     pub fn enable_vbat(&self) -> Vbat {
-        #[cfg(not(adc_g0))]
-        T::common_regs().ccr().modify(|reg| {
-            reg.set_ch18sel(true);
-        });
-        #[cfg(adc_g0)]
-        T::regs().ccr().modify(|reg| {
-            reg.set_vbaten(true);
-        });
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                T::regs().ccr().modify(|reg| {
+                    reg.set_vbaten(true);
+                });
+            } else if #[cfg(adc_h5)] {
+                T::common_regs().ccr().modify(|reg| {
+                    reg.set_vbaten(true);
+                });
+            } else {
+                T::common_regs().ccr().modify(|reg| {
+                    reg.set_ch18sel(true);
+                });
+            }
+        }
 
         Vbat {}
     }
@@ -205,16 +247,21 @@ impl<'d, T: Instance> Adc<'d, T> {
         val
     }
 
-    #[cfg(adc_g0)]
     fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
-        T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
-    }
-
-    #[cfg(not(adc_g0))]
-    fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
-        let sample_time = sample_time.into();
-        T::regs()
-            .smpr(ch as usize / 10)
-            .modify(|reg| reg.set_smp(ch as usize % 10, sample_time));
+        cfg_if! {
+            if #[cfg(adc_g0)] {
+                T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
+            } else if #[cfg(adc_h5)] {
+                match _ch {
+                    0..=9 => T::regs().smpr1().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())),
+                    _ => T::regs().smpr2().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())),
+                }
+            } else {
+                let sample_time = sample_time.into();
+                T::regs()
+                    .smpr(ch as usize / 10)
+                    .modify(|reg| reg.set_smp(ch as usize % 10, sample_time));
+            }
+        }
     }
 }