diff --git a/src/adc.rs b/src/adc.rs index 4d23c136..ce36d459 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -22,6 +22,14 @@ use crate::{ use pac::{ADC1, ADC_COMMON}; use stable_deref_trait::StableDeref; +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +use crate::gpio::AnalogPin; + /// Vref internal signal, used for calibration pub struct Vref; @@ -31,6 +39,42 @@ pub struct Vbat; /// Core temperature internal signal pub struct Temperature; +// TODO: Avoid this hack +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +impl AnalogPin for Vref { + fn connect_adc(&mut self) {} + fn disconnect_adc(&mut self) {} +} + +// TODO: Avoid this hack +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +impl AnalogPin for Vbat { + fn connect_adc(&mut self) {} + fn disconnect_adc(&mut self) {} +} + +// TODO: Avoid this hack +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +impl AnalogPin for Temperature { + fn connect_adc(&mut self) {} + fn disconnect_adc(&mut self) {} +} + /// Analog to Digital converter interface pub struct ADC { pub(crate) adc: ADC1, @@ -447,6 +491,15 @@ where self.start_conversion(); while !self.has_completed_sequence() {} + #[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" + ))] + // Connect the pin to the ADC + channel.connect_adc(); + // Read ADC value first time and discard it, as per errata sheet. // The errata states that if we do conversions slower than 1 kHz, the // first read ADC value can be corrupted, so we discard it and measure again. @@ -458,6 +511,15 @@ where // Read ADC value let val = self.get_data(); + #[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" + ))] + // Disconnect the pin from the ADC + channel.disconnect_adc(); + // Disable ADC self.disable(); @@ -638,11 +700,28 @@ impl Default for SampleTime { } } +#[cfg(not(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +)))] /// Implemented for all types that represent ADC channels pub trait Channel: EmbeddedHalChannel { fn set_sample_time(&mut self, adc: &ADC1, sample_time: SampleTime); } +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +/// Implemented for all types that represent ADC channels +pub trait Channel: EmbeddedHalChannel + AnalogPin { + fn set_sample_time(&mut self, adc: &ADC1, sample_time: SampleTime); +} + macro_rules! adc_pins { ( $( diff --git a/src/gpio.rs b/src/gpio.rs index 94a8427c..93a70380 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -205,6 +205,44 @@ where } } +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +/// Analog Pin +pub trait AnalogPin { + fn connect_adc(&mut self); + fn disconnect_adc(&mut self); +} + +#[cfg(any( + feature = "stm32l471", + feature = "stm32l475", + feature = "stm32l476", + feature = "stm32l486" +))] +impl AnalogPin for Pin { + #[inline(always)] + fn connect_adc(&mut self) { + unsafe { + (*Gpio::

::ptr()) + .ascr + .modify(|r, w| w.bits(r.bits() | (1 << N))); + } + } + + #[inline(always)] + fn disconnect_adc(&mut self) { + unsafe { + (*Gpio::

::ptr()) + .ascr + .modify(|r, w| w.bits(r.bits() & !(1 << N))); + } + } +} + /// Opaque MODER register pub struct MODER { _0: (),