Skip to content

Commit

Permalink
Implement ADC self-calibration (#233)
Browse files Browse the repository at this point in the history
* Implement ADC self-calibration

Implement the ACD self-calibration procedure, which is defined in the
RM377 reference manual as follows:

The ADC has a calibration feature. During the procedure, the ADC
calculates a calibration factor which is internally applied to the ADC
until the next ADC power-off. The application must not use the ADC
during calibration and must wait until it is complete.  Calibration
should be performed before starting A/D convers

* Wait for hardware to clear ADCAL after calibration

The reference manual says that software should wait until ADCAL = 0.
Do that instead of being paranoid and eventually timing out if this does
not happen.

---------

Co-authored-by: Javier Cardona <javier@cardonabits.com>
  • Loading branch information
jcard0na and Javier Cardona authored Jan 23, 2024
1 parent 7041775 commit d20524c
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ impl Adc<Ready> {
self.precision = precision;
}

/// Trigger internal ADC calibration
///
/// This process is documented in Reference Manual RM377, section 13.3.3
/// Calibration (ADCAL)
pub fn calibrate(&mut self) -> Result<(), Error> {
if self._state != Ready
|| self.rb.cr.read().aden().bit_is_set()
|| self.rb.cfgr1.read().dmaen().bit_is_set()
{
return Err(Error::InvalidAdcState);
}

self.rb.cr.modify(|_, w| w.adcal().set_bit());
while self.rb.cr.read().adcal().bit_is_set() {}
Ok(())
}

/// Starts a continuous conversion process
///
/// The `channel` argument specifies which channel should be converted.
Expand Down Expand Up @@ -321,6 +338,7 @@ where
}

/// Indicates that the ADC peripheral is ready
#[derive(PartialEq)]
pub struct Ready;

/// Indicates that the ADC peripheral is performing conversions
Expand Down Expand Up @@ -615,6 +633,9 @@ pub enum Error {
/// just keeps writing more values. It does mean that some values in the
/// buffer were overwritten though.
BufferOverrun,

/// Invalid ADC state for requested operation
InvalidAdcState,
}

macro_rules! int_adc {
Expand Down

0 comments on commit d20524c

Please sign in to comment.