pub struct Adc<'d, T: Instance, M: Mode> { /* private fields */ }Expand description
Analog to Digital driver.
Implementations§
Source§impl<'d, T: Instance, M: Mode> Adc<'d, T, M>where
T::Regs: InjectedRegs,
impl<'d, T: Instance, M: Mode> Adc<'d, T, M>where
T::Regs: InjectedRegs,
Sourcepub fn setup_injected_conversions<'a, const N: usize, IM: InjectedMode>(
self,
_irq: impl Binding<T::Interrupt, IM::Handler<T>> + 'a,
sequence: [(BorrowedAdcChannel<'a, T>, SampleTimeOf<T>); N],
trigger: InjectedAdcTrigger<T>,
mode: IM,
) -> InjectedAdc<'a, T::Regs, IM>
pub fn setup_injected_conversions<'a, const N: usize, IM: InjectedMode>( self, _irq: impl Binding<T::Interrupt, IM::Handler<T>> + 'a, sequence: [(BorrowedAdcChannel<'a, T>, SampleTimeOf<T>); N], trigger: InjectedAdcTrigger<T>, mode: IM, ) -> InjectedAdc<'a, T::Regs, IM>
Configures the ADC for injected conversions.
Injected conversions are separate from the regular conversion sequence and are typically triggered by software or an external event. This method sets up a fixed-length sequence of injected channels with specified sample times, the trigger source, and whether the end-of-sequence interrupt should be enabled.
§Parameters
sequence: An array of tuples containing the ADC channels and their sample times. The lengthNdetermines the number of injected ranks to configure (maximum 4).trigger: The trigger source that starts the injected conversion sequence.mode:Asyncto read results with the interrupt (the ADC interrupt must be bound),Blockingto read them withInjectedAdc::read_latest.
§Returns
An InjectedAdc instance that represents the configured injected sequence.
§Panics
This function will panic if sequence is empty or longer than the number of injected ranks.
Sourcepub fn into_ring_buffered_and_injected<'a, 'b, const N: usize, D: RxDma<T>, IM: InjectedMode>(
self,
dma: Peri<'a, D>,
dma_buf: &'a mut [u16],
_irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a + Binding<T::Interrupt, IM::Handler<T>> + 'b,
regular_sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'a, T>, SampleTimeOf<T>)>,
regular_trigger: Option<RegularAdcTrigger<T>>,
injected_sequence: [(BorrowedAdcChannel<'b, T>, SampleTimeOf<T>); N],
injected_trigger: InjectedAdcTrigger<T>,
mode: IM,
) -> (RingBufferedAdc<'a, T::Regs>, InjectedAdc<'b, T::Regs, IM>)
pub fn into_ring_buffered_and_injected<'a, 'b, const N: usize, D: RxDma<T>, IM: InjectedMode>( self, dma: Peri<'a, D>, dma_buf: &'a mut [u16], _irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a + Binding<T::Interrupt, IM::Handler<T>> + 'b, regular_sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'a, T>, SampleTimeOf<T>)>, regular_trigger: Option<RegularAdcTrigger<T>>, injected_sequence: [(BorrowedAdcChannel<'b, T>, SampleTimeOf<T>); N], injected_trigger: InjectedAdcTrigger<T>, mode: IM, ) -> (RingBufferedAdc<'a, T::Regs>, InjectedAdc<'b, T::Regs, IM>)
Configures ADC for both regular conversions with a ring-buffered DMA and injected conversions.
§Parameters
dma: The DMA peripheral to use for the ring-buffered ADC transfers.dma_buf: The buffer to store DMA-transferred samples for regular conversions.regular_sequence: The sequence of channels and their sample times for regular conversions.regular_trigger: The trigger for regular conversions (Nonefor continuous).injected_sequence: An array of channels and sample times for injected conversions (lengthN).injected_trigger: The trigger source for injected conversions.
Injected conversions are typically used with interrupts. If ADC1 and ADC2 are used in dual mode, it is recommended to enable interrupts only for the ADC whose sequence takes the longest to complete.
§Returns
A tuple containing:
RingBufferedAdc— the configured ADC for regular conversions using DMA.InjectedAdc— the configured ADC for injected conversions.
Source§impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
Sourcepub fn enable_vrefint(&mut self) -> VrefIntwhere
T: HasInternalChannel<VrefInt>,
pub fn enable_vrefint(&mut self) -> VrefIntwhere
T: HasInternalChannel<VrefInt>,
Enable the internal voltage reference channel.
Sourcepub fn enable_temperature(&mut self) -> Temperaturewhere
T: HasInternalChannel<Temperature>,
pub fn enable_temperature(&mut self) -> Temperaturewhere
T: HasInternalChannel<Temperature>,
Enable the internal temperature sensor channel.
The sensor needs a long sample time (see the datasheet for ts_temp), and on some chips
shares its channel with VBAT: enabling both returns VBAT.
Sourcepub fn enable_vbat(&mut self) -> Vbatwhere
T: HasInternalChannel<Vbat>,
pub fn enable_vbat(&mut self) -> Vbatwhere
T: HasInternalChannel<Vbat>,
Enable the VBAT channel. This connects VBAT to an internal divider, which draws current
from the battery for as long as it is enabled; use disable_vbat
when done.
Sourcepub fn disable_vbat(&mut self, _vbat: Vbat)where
T: HasInternalChannel<Vbat>,
pub fn disable_vbat(&mut self, _vbat: Vbat)where
T: HasInternalChannel<Vbat>,
Disconnect the VBAT divider.
Sourcepub fn enable_vddcore(&mut self) -> VddCorewhere
T: HasInternalChannel<VddCore>,
pub fn enable_vddcore(&mut self) -> VddCorewhere
T: HasInternalChannel<VddCore>,
Enable the core supply voltage channel.
Sourcepub fn enable_dac(&mut self, dac_channel: u8) -> Dacwhere
T: HasInternalChannel<Dac>,
pub fn enable_dac(&mut self, dac_channel: u8) -> Dacwhere
T: HasInternalChannel<Dac>,
Enable the internal connection to the DAC output.
dac_channel selects which DAC output is connected on chips that mux several onto one ADC
channel (0 for OUT1, 1 for OUT2); it is ignored elsewhere.
Source§impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
Sourcepub fn enable_watchdog(
&mut self,
watchdog: WatchdogIndex,
channels: WatchdogChannels,
low_threshold: u32,
high_threshold: u32,
) -> AnalogWatchdog<T, M>
pub fn enable_watchdog( &mut self, watchdog: WatchdogIndex, channels: WatchdogChannels, low_threshold: u32, high_threshold: u32, ) -> AnalogWatchdog<T, M>
Enable an analog watchdog and return a guard.
watchdog selects which of the hardware watchdogs to use. channels controls which ADC
channels are monitored; see WatchdogChannels for which variants are valid for each
watchdog. low_threshold and high_threshold are raw ADC counts in the same space as
the data register for the currently configured resolution and oversampling. The
watchdog fires when a sample falls outside [low_threshold, high_threshold].
Watchdogs 2 and 3 of 12-bit ADCs only compare the 8 most significant bits of a sample.
Call AnalogWatchdog::wait to detect threshold crossings concurrently with other
conversions, or AnalogWatchdog::monitor for self-contained single-pin monitoring
(which temporarily borrows the ADC).
§Panics
Panics if low_threshold > high_threshold, if the ADC does not have the requested
watchdog, or if a channel selection variant is used that is not supported by the chosen
watchdog.
Source§impl<'d, T: Instance> Adc<'d, T, Async>
impl<'d, T: Instance> Adc<'d, T, Async>
Sourcepub fn new(
adc: Peri<'d, T>,
_irqs: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd,
config: Config,
) -> Self
pub fn new( adc: Peri<'d, T>, _irqs: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd, config: Config, ) -> Self
Create a new ADC driver with its interrupt bound.
Sourcepub async fn read<'a>(
&mut self,
channel: impl BorrowedChannel<'a, T>,
sample_time: SampleTimeOf<T>,
) -> u16
pub async fn read<'a>( &mut self, channel: impl BorrowedChannel<'a, T>, sample_time: SampleTimeOf<T>, ) -> u16
Read a channel once, waiting for the end-of-conversion interrupt.
Source§impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
impl<'d, T: Instance, M: Mode> Adc<'d, T, M>
Sourcepub fn set_resolution(&mut self, resolution: Resolution)
pub fn set_resolution(&mut self, resolution: Resolution)
Set the conversion resolution.
Sourcepub fn resolution(&self) -> Resolution
pub fn resolution(&self) -> Resolution
The currently configured resolution.
Sourcepub fn sample_time_for_us(&self, us: u32) -> SampleTimeOf<T>where
T::Regs: SampleTimes,
pub fn sample_time_for_us(&self, us: u32) -> SampleTimeOf<T>where
T::Regs: SampleTimes,
Pick the shortest sample time that samples for at least us microseconds.
Sourcepub fn blocking_read<'a>(
&mut self,
channel: impl BorrowedChannel<'a, T>,
sample_time: SampleTimeOf<T>,
) -> u16
pub fn blocking_read<'a>( &mut self, channel: impl BorrowedChannel<'a, T>, sample_time: SampleTimeOf<T>, ) -> u16
Read a channel once, busy-waiting for the conversion.
Sourcepub async fn read_sequence<'a, 'ch: 'a, D: RxDma<T>>(
&mut self,
rx_dma: Peri<'a, D>,
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
trigger: Option<RegularAdcTrigger<T>>,
readings: &mut [u16],
)
pub async fn read_sequence<'a, 'ch: 'a, D: RxDma<T>>( &mut self, rx_dma: Peri<'a, D>, irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a, sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>, trigger: Option<RegularAdcTrigger<T>>, readings: &mut [u16], )
Read one or multiple regular channels using DMA.
readings must have a length that is a multiple of the length of the sequence iterator;
the sequence is repeated until it is full, continuously or once per trigger event.
Example
use embassy_stm32::adc::{Adc, AdcChannel}
let mut adc = Adc::new_blocking(p.ADC1, Default::default());
let mut adc_pin0 = p.PA0.into();
let mut adc_pin1 = p.PA1.into();
let mut measurements = [0u16; 2];
adc.read_sequence(
p.DMA1_CH2.reborrow(),
Irqs,
[
(&mut *adc_pin0, SampleTime::CYCLES160_5),
(&mut *adc_pin1, SampleTime::CYCLES160_5),
]
.into_iter(),
None,
&mut measurements,
)
.await;
defmt::info!("measurements: {}", measurements);Note: the ADC is reconfigured on each call. Use configure_sequence
or into_ring_buffered to convert the same sequence repeatedly.
Note: ADCs without a fully configurable sequencer (F0, L0, and G0-class ADCs with more than 8 channels or channels above 14) can only scan channels in ascending or descending order, with a single sample time. This method panics if the hardware cannot deliver the requested sequence.
Sourcepub unsafe fn configure_transfer<'adc, 'ch, D: RxDma<T>, W: Word>(
&'adc mut self,
rx_dma: Peri<'adc, D>,
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'd,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
trigger: RegularAdcTrigger<T>,
dst: *mut W,
) -> ConfiguredTransfer<'adc, T::Regs>where
'ch: 'adc,
pub unsafe fn configure_transfer<'adc, 'ch, D: RxDma<T>, W: Word>(
&'adc mut self,
rx_dma: Peri<'adc, D>,
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'd,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
trigger: RegularAdcTrigger<T>,
dst: *mut W,
) -> ConfiguredTransfer<'adc, T::Regs>where
'ch: 'adc,
Configure an ADC channel sequence once and return a ConfiguredTransfer for repeated
DMA reads to peripherals such as FMAC or CORDIC.
Use Adc::configure_sequence instead if you don’t want to pipe the results directly
to a peripheral.
§Safety
dst must be a valid peripheral data register for the lifetime of the returned value.
§Notes
- The channel sequence is programmed into the ADC sequence registers once here and
remains fixed for the lifetime of the returned
ConfiguredTransfer. - Call this method AFTER the targeted peripheral is ready to begin receiving the transfer.
Sourcepub fn configure_sequence<'adc, 'ch, D: RxDma<T>>(
&'adc mut self,
rx_dma: Peri<'adc, D>,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'd,
) -> ConfiguredSequence<'adc, T::Regs>where
'ch: 'adc,
pub fn configure_sequence<'adc, 'ch, D: RxDma<T>>(
&'adc mut self,
rx_dma: Peri<'adc, D>,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'd,
) -> ConfiguredSequence<'adc, T::Regs>where
'ch: 'adc,
Configure an ADC channel sequence once and return a ConfiguredSequence for repeated
DMA reads without reprogramming the sequence each time.
Use Adc::read_sequence instead if you only need a single one-shot transfer.
§Parameters
rx_dma: The DMA channel to use for transfers.sequence: Iterator of channels and sample times.
§Returns
A ConfiguredSequence whose read method triggers one
DMA conversion of the pre-configured sequence per call.
Sourcepub fn into_ring_buffered<'a, 'ch, D: RxDma<T>>(
self,
dma: Peri<'a, D>,
dma_buf: &'a mut [u16],
irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a,
sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>,
trigger: Option<RegularAdcTrigger<T>>,
) -> RingBufferedAdc<'a, T::Regs>
pub fn into_ring_buffered<'a, 'ch, D: RxDma<T>>( self, dma: Peri<'a, D>, dma_buf: &'a mut [u16], irq: impl Binding<D::Interrupt, InterruptHandler<D>> + 'a, sequence: impl ExactSizeIterator<Item = (BorrowedAdcChannel<'ch, T>, SampleTimeOf<T>)>, trigger: Option<RegularAdcTrigger<T>>, ) -> RingBufferedAdc<'a, T::Regs>
Configures the ADC to use a DMA ring buffer for continuous data acquisition.
Use the RingBufferedAdc::read method to retrieve measurements from the DMA ring buffer.
The read buffer should be exactly half the size of dma_buf. When using triggered mode, it
is recommended to configure dma_buf as a double buffer so that one half can be read while
the other half is being filled by the DMA, preventing data loss. The trigger period of the
ADC effectively defines the period at which the buffer should be read.
If continuous conversion mode is selected (no trigger), the provided dma_buf must be
large enough to prevent DMA buffer overruns. Its length should be a multiple of the number
of ADC channels being measured. For example, if 3 channels are measured and you want to
store 40 samples per channel, the buffer length should be 3 * 40 = 120.
Note: ADCs without a fully configurable sequencer (see read_sequence)
restrict the channel order and sample times; this method panics if the hardware cannot
deliver the requested sequence.