Struct stm32wlxx_hal::adc::Adc

source ·
pub struct Adc { /* private fields */ }
Available on non-crate feature stm32wl5x_cm0p only.
Expand description

Analog to digital converter driver.

Implementations§

source§

impl Adc

source

pub fn new(adc: ADC, clk: Clk, rcc: &mut RCC) -> Self

Create a new ADC driver from a ADC peripheral.

This will enable the ADC clock and reset the ADC peripheral.

Note: This will select the clock source, but you are responsible for enabling that clock source.

Example

Initialize the ADC with HSI16.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);

Initialize the ADC with PCLK/4.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
source

pub const unsafe fn new_no_init(adc: ADC) -> Self

Create a new ADC driver from an ADC peripheral without initialization.

This is a slightly safer version of steal.

Safety
  1. Reset the ADC peripheral if determinism is required.
  2. Enable the ADC peripheral clock before using the ADC.
  3. Select the clock source if a non-default clock is required.
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();

// safety: nothing is using the peripheral
unsafe { Adc::pulse_reset(&mut dp.RCC) };

Adc::enable_clock(&mut dp.RCC);

// safety: ADC peripheral has been reset and clocks are enabled
let mut adc: Adc = unsafe { Adc::new_no_init(dp.ADC) };

// select the ADC clock, optional
adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
source

pub fn free(self) -> ADC

Free the ADC peripheral from the driver.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
// ... use ADC
let adc: pac::ADC = adc.free();
source

pub unsafe fn steal() -> Adc

Steal the ADC peripheral from whatever is currently using it.

This will not initialize the ADC (unlike new).

Safety
  1. Ensure that the code stealing the ADC has exclusive access to the peripheral. Singleton checks are bypassed with this method.
  2. Reset the ADC peripheral if determinism is required.
  3. Enable the ADC peripheral clock before using the ADC.
  4. Select the clock source if a non-default clock is required.
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let _: pac::ADC = dp.ADC;

unsafe { Adc::pulse_reset(&mut dp.RCC) };

Adc::enable_clock(&mut dp.RCC);

let mut adc: Adc = unsafe { Adc::steal() };

// select the ADC clock, optional
adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
source

pub fn set_clock_source(&mut self, clk: Clk, rcc: &mut RCC)

Set the ADC clock source.

Panics
  • (debug) ADC is enabled
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);

// change the clock source
adc.disable();
adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
source

pub fn clock_source(&self, rcc: &RCC) -> Option<Clk>

Get the ADC clock source.

Returns None if the ADC is configured for an asynchronous clock, but no asynchronous clock is selected.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);

assert_eq!(adc.clock_source(&dp.RCC), Some(adc::Clk::PClkDiv4));
source

pub unsafe fn disable_clock(rcc: &mut RCC)

Disable the ADC clock.

Safety
  1. Ensure nothing is using the ADC before disabling the clock.
  2. You are responsible for re-enabling the clock before using the ADC.
source

pub fn enable_clock(rcc: &mut RCC)

Enable the ADC clock.

new will enable clocks for you.

source

pub unsafe fn pulse_reset(rcc: &mut RCC)

Pulse the ADC reset.

new will pulse reset for you.

Safety
  1. Ensure nothing is using the ADC before calling this function.
  2. You are responsible for setting up the ADC after a reset.
source

pub fn clock_hz(&self, rcc: &RCC) -> u32

Calculate the ADC clock frequency in hertz.

Note: If the ADC prescaler register erroneously returns a reserved value the code will default to an ADC prescaler of 1.

Fractional frequencies will be rounded towards zero.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let adc: Adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
assert_eq!(adc.clock_hz(&dp.RCC), 16_000_000);
source

pub unsafe fn unmask_irq()

Available on crate feature rt only.

Unmask the ADC IRQ in the NVIC.

Safety

This can break mask-based critical sections.

Example
unsafe { stm32wlxx_hal::adc::Adc::unmask_irq() };
source

pub fn mask_irq()

Available on crate feature rt only.

Mask the ADC IRQ in the NVIC.

Example
unsafe { stm32wlxx_hal::adc::Adc::mask_irq() }
source

pub fn set_sample_times(&mut self, mask: u32, sel0: Ts, sel1: Ts)

Set sample times for all channels.

For each bit in the mask:

  • 0: Sample time is set by the sel0 argument.
  • 1: Sample time is set by the sel1 argument.
Panics
  • (debug) An ADC conversion is in-progress
Example

Set ADC channels In0 and In1 (pins B13 and B14 respectively) and the internal VBAT to a sample time of 39.5 ADC clock cycles, and set all other channels to a sample time of 160.5 clock cycles.

use stm32wlxx_hal::{
    self as hal,
    adc::{self, Adc, Ts},
    gpio::pins::{B13, B14},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.set_sample_times(
    B14::ADC_CH.mask() | B13::ADC_CH.mask() | adc::Ch::Vbat.mask(),
    Ts::Cyc160,
    Ts::Cyc39,
);
source

pub fn set_max_sample_time(&mut self)

Sets all channels to the maximum sample time.

This is a helper for testing and rapid prototyping purpose because set_sample_times is verbose.

This method is equivalent to this:

use stm32wlxx_hal::adc::Ts;

adc.set_sample_times(0, Ts::Cyc160, Ts::Cyc160);
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.set_max_sample_time();
source

pub fn set_isr(&mut self, isr: u32)

Clear interrupts.

Example

Clear all interrupts.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.set_isr(adc::irq::ALL);
source

pub fn isr() -> R

Read the interrupt status.

Example

Check if the ADC is ready.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
// this will be false because the ADC is not enabled
let ready: bool = Adc::isr().adrdy().is_ready();
source

pub fn set_ier(&mut self, ier: u32)

Enable and disable interrupts.

Example

Enable all IRQs

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.set_ier(adc::irq::ALL);
source

pub fn start_chsel(&mut self, ch: u32)

Configure the channel sequencer.

This is advanced ADC usage, most of the time you will want to use a one of the available sample methods that will configure this.

This will not poll for completion, when this method returns the channel configuration may not be ready.

Panics
  • (debug) ADC conversion is in-progress.
Example

Select the ADC VBAT channel.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.start_chsel(adc::Ch::Vbat.mask());
while Adc::isr().ccrdy().is_not_complete() {}
source

pub fn start_conversion(&mut self)

Start an ADC conversion.

This is advanced ADC usage, most of the time you will want to use a one of the available sample methods that will configure this.

This will not poll for completion, when this method returns the AD conversion may not be complete.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
Example

See data.

source

pub fn stop_conversion(&mut self)

Stop an ADC conversion if there is one in-progress.

source

pub fn data(&self) -> u16

Read the ADC conversion data.

This is advanced ADC usage, most of the time you will want to use a one of the available sample methods.

Example

Read the ADC VBAT channel.

use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);

// calibrate the ADC before it is enabled
adc.calibrate(&mut delay);

// enable the ADC
adc.enable();

// set the sample times to the maximum (160.5 ADC cycles)
adc.set_max_sample_time();

// select the Vbat channel and poll for completion
adc.start_chsel(adc::Ch::Vbat.mask());
while Adc::isr().ccrdy().is_not_complete() {}

// start the conversion and poll for completion
adc.start_conversion();
while Adc::isr().eoc().is_not_complete() {}

// read the ADC data
let vbat: u16 = adc.data();
source

pub fn enable_tsen(&mut self)

Enable the temperature sensor.

You MUST wait for the temperature sensor to start up (TS_START_TYP or TS_START_MAX) before the samples will be accurate.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.enable_tsen();
// wait for the temperature sensor to startup
delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
source

pub fn disable_tsen(&mut self)

Disable the temperature sensor.

source

pub fn is_tsen_enabled(&mut self) -> bool

Returns true if the temperature sensor is enabled.

source

pub fn temperature(&mut self) -> Ratio<i16>

Get the junction temperature.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
  • (debug) Temperature sensor is not enabled
Sample Time

You must set a sampling time with set_sample_times greater than or equal to TS_MIN_SAMPLE before calling this method. When in doubt use the maximum sampling time, Ts::Cyc160.

Calibration

The temperature calibration provided on-chip appears to be for an uncalibrated ADC, though I can find no mention of this in the datasheet.

If the ADC has been calibrated with calibrate the calibration offset will be removed from the sample.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.enable();
adc.enable_tsen();
delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
adc.set_max_sample_time();

let tj: i16 = adc.temperature().to_integer();
source

pub fn enable_vref(&mut self)

Enable the internal voltage reference.

source

pub fn disable_vref(&mut self)

Disable the internal voltage reference.

source

pub fn is_vref_enabled(&mut self) -> bool

Returns true if the internal voltage reference is enabled.

source

pub fn enable_oversampling( &mut self, ratio: OversampleRatio, shift: OversampleShift )

Enable oversampling.

Panics
  • (debug) ADC is enabled
source

pub fn disable_oversampling(&mut self)

Disables oversampling.

Panics
  • (debug) ADC is enabled
source

pub fn is_oversampling_enabled(&mut self) -> bool

Returns true if oversampling is enabled.

source

pub fn vref(&mut self) -> u16

Read the internal voltage reference.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
  • (debug) Voltage reference is not enabled
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);
adc.set_max_sample_time();
adc.enable();
adc.enable_vref();

let vref: u16 = adc.vref();
let vref_cal: u16 = adc::vref_cal();
let error: i16 = ((vref as i16) - (vref_cal as i16)).abs();
assert!(error < 10);
source

pub fn dac(&mut self) -> u16

Sample the DAC output.

The DAC must be configured to output to chip peripherals for this to work as expected.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    dac::{Dac, ModeChip},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);
adc.set_max_sample_time();

let mut dac: Dac = Dac::new(dp.DAC, &mut dp.RCC);
dac.set_mode_chip(ModeChip::Norm);

dac.setup_soft_trigger();
dac.soft_trigger(1234);
// should be in the same ballpark as the DAC output
let sample: u16 = adc.dac();
source

pub fn pin<P: AdcCh>(&mut self, pin: &Analog<P>) -> u16

Sample a GPIO pin.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    gpio::{pins::B4, Analog, PortB},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);
adc.set_max_sample_time();
adc.enable();

let gpiob: PortB = PortB::split(dp.GPIOB, &mut dp.RCC);
let b4: Analog<B4> = cortex_m::interrupt::free(|cs| Analog::new(gpiob.b4, cs));

let sample: u16 = adc.pin(&b4);
source

pub fn enable_vbat(&mut self)

Enable VBAT.

To prevent any unwanted consumption on the battery, it is recommended to enable the bridge divider only when needed for ADC conversion.

source

pub fn disable_vbat(&mut self)

Disable VBAT.

source

pub fn is_vbat_enabled(&self) -> bool

Returns true if VBAT is enabled.

source

pub fn vbat(&mut self) -> u16

Sample the VBAT pin.

This is internally connected to a bridge divider, the converted digital value is a third the VBAT voltage.

Panics
  • (debug) ADC is not enabled
  • (debug) ADC has a pending disable request
  • (debug) VBAT is not enabled
Example
use stm32wlxx_hal::{
    self as hal,
    adc::{self, Adc},
    dac::{Dac, ModeChip},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);

adc.enable();
adc.enable_vbat();
adc.set_max_sample_time();
let sample: u16 = adc.vbat();
source§

impl Adc

source

pub fn is_enabled(&self) -> bool

Returns true if the ADC is enabled.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
assert_eq!(adc.is_enabled(), false);
source

pub fn disable_in_progress(&self) -> bool

Returns true if an ADC disable command is in-progress.

source

pub fn is_disabled(&self) -> bool

Returns true if the ADC is disabled, and there is no disable command in-progress.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
assert_eq!(adc.is_disabled(), true);
source

pub fn start_enable(&mut self) -> bool

Start the ADC enable procedure.

This is advanced ADC usage, most of the time you will want to use enable.

This will not poll for completion, when this method returns the ADC may not be enabled.

The method returns true if the caller function should poll for completion (the ADC was not already enabled), if the ADC was already enabled and the ADRDY interrupt was cleared then the ADRDY bit will not be set again after calling this method which can lead to polling loops that will never terminate.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
if adc.start_enable() {
    while Adc::isr().adrdy().is_not_ready() {}
}
source

pub fn enable(&mut self)

Enable the ADC and poll for completion.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.enable();
source

pub fn start_disable(&mut self)

Start the ADC disable procedure.

This is advanced ADC usage, most of the time you will want to use disable.

This will not poll for completion, when this function returns the ADC may not be disabled.

This will stop any conversions in-progress.

The ADC takes about 20 CPU cycles to disable with a 48MHz sysclk and the ADC on the 16MHz HSI clock.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.enable();
// ... use ADC
adc.start_disable();
while !adc.is_disabled() {}
source

pub fn disable(&mut self)

Disable the ADC and poll for completion.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
adc.enable();
// ... use ADC
adc.disable();
source§

impl Adc

source

pub fn calibrate<D: DelayUs<u8>>(&mut self, delay: &mut D)

Calibrate the ADC for additional accuracy.

Calibration should be performed before starting A/D conversion. It removes the offset error which may vary from chip to chip due to process variation.

The calibration factor is lost in the following cases:

  • The power supply is removed from the ADC (for example when entering STANDBY or VBAT mode)
  • The ADC peripheral is reset.

This will disable the ADC if it is not already disabled.

This function is the simple way to calibrate the ADC, you can use these methods to achieve the same results if you desire finer controls:

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);
source

pub fn enable_vreg(&mut self)

Enable the ADC voltage regulator for calibration.

This is advanced ADC usage, most of the time you will want to use calibrate.

This will disable the ADC and DMA request generation if not already disabled.

You MUST wait T_ADCVREG_SETUP before the voltage regulator output is available. This delay is not performed for you.

Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.enable_vreg();
delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
source

pub fn disable_vreg(&mut self)

Disable the ADC voltage regulator.

Panics
  • (debug) ADC is enabled
source

pub fn start_calibrate(&mut self)

Start the ADC calibration.

This is advanced ADC usage, most of the time you will want to use calibrate.

When this function returns the ADC calibration has started, but may not have finished. Check if the ADC calibration has finished with Adc::isr.

Panics
  • (debug) ADC is enabled.
  • (debug) ADC voltage regulator is not enabled.
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);

adc.enable_vreg();
delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
adc.start_calibrate();
// datasheet says this takes 82 ADC clock cycles
// my measurements are closer to 120 ADC clock cycles
while Adc::isr().eocal().is_not_complete() {}
source

pub fn calfact(&self) -> u8

Get the ADC calibration factor.

Example

See force_cal.

source

pub fn force_cal(&mut self, calfact: u8)

Force the ADC calibration.

The calibration factor is lost each time power is removed from the ADC (for example when entering standby or VBAT mode) It is possible to save and restore the calibration factor with firmware to save time when re-starting the ADC (as long as temperature and voltage are stable during the ADC power-down).

Panics
  • (debug) ADC is not enabled
  • (debug) ADC conversion is in-progress
Example
use stm32wlxx_hal::{
    adc::{self, Adc},
    pac, rcc,
    util::new_delay,
};

let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();

// enable the HSI16 source clock
dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
while dp.RCC.cr.read().hsirdy().is_not_ready() {}

let mut delay = new_delay(cp.SYST, &dp.RCC);
let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
adc.calibrate(&mut delay);

// save the calibration factor
let calfact: u8 = adc.calfact();

// restore the calibration
adc.enable(); // ADC must be enabled to restore the calibration
adc.force_cal(calfact);

Trait Implementations§

source§

impl Debug for Adc

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl RefUnwindSafe for Adc

§

impl Send for Adc

§

impl !Sync for Adc

§

impl Unpin for Adc

§

impl UnwindSafe for Adc

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.