stm32/adc: Remove voltage and temperature conversions
This commit is contained in:
		| @@ -86,7 +86,6 @@ pub use sample_time::SampleTime; | |||||||
|  |  | ||||||
| pub struct Adc<'d, T: Instance> { | pub struct Adc<'d, T: Instance> { | ||||||
|     sample_time: SampleTime, |     sample_time: SampleTime, | ||||||
|     calibrated_vdda: u32, |  | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut T>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -122,7 +121,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||||||
|  |  | ||||||
|         Self { |         Self { | ||||||
|             sample_time: Default::default(), |             sample_time: Default::default(), | ||||||
|             calibrated_vdda: VDDA_CALIB_MV, |  | ||||||
|             phantom: PhantomData, |             phantom: PhantomData, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -162,29 +160,10 @@ impl<'d, T: Instance> Adc<'d, T> { | |||||||
|         Temperature {} |         Temperature {} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Calculates the system VDDA by sampling the internal VREF channel and comparing |  | ||||||
|     /// to the expected value. If the chip's VDDA is not stable, run this before each ADC |  | ||||||
|     /// conversion. |  | ||||||
|     pub fn calibrate(&mut self, vref: &mut Vref) -> u32 { |  | ||||||
|         let old_sample_time = self.sample_time; |  | ||||||
|         self.sample_time = SampleTime::Cycles239_5; |  | ||||||
|  |  | ||||||
|         let vref_samp = self.read(vref); |  | ||||||
|         self.sample_time = old_sample_time; |  | ||||||
|  |  | ||||||
|         self.calibrated_vdda = (ADC_MAX * VREF_INT) / u32::from(vref_samp); |  | ||||||
|         self.calibrated_vdda |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pub fn set_sample_time(&mut self, sample_time: SampleTime) { |     pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||||||
|         self.sample_time = sample_time; |         self.sample_time = sample_time; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Convert a measurement to millivolts |  | ||||||
|     pub fn to_millivolts(&self, sample: u16) -> u16 { |  | ||||||
|         ((u32::from(sample) * self.calibrated_vdda) / ADC_MAX) as u16 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Perform a single conversion. |     /// Perform a single conversion. | ||||||
|     fn convert(&mut self) -> u16 { |     fn convert(&mut self) -> u16 { | ||||||
|         unsafe { |         unsafe { | ||||||
|   | |||||||
| @@ -80,15 +80,6 @@ impl super::sealed::InternalChannel<ADC1> for Temperature { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl Temperature { | impl Temperature { | ||||||
|     /// Converts temperature sensor reading in millivolts to degrees celcius |  | ||||||
|     pub fn to_celcius(sample_mv: u16) -> f32 { |  | ||||||
|         // From 6.3.22 Temperature sensor characteristics |  | ||||||
|         const V25: i32 = 760; // mV |  | ||||||
|         const AVG_SLOPE: f32 = 2.5; // mV/C |  | ||||||
|  |  | ||||||
|         (sample_mv as i32 - V25) as f32 / AVG_SLOPE + 25.0 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Time needed for temperature sensor readings to stabilize |     /// Time needed for temperature sensor readings to stabilize | ||||||
|     pub fn start_time_us() -> u32 { |     pub fn start_time_us() -> u32 { | ||||||
|         10 |         10 | ||||||
| @@ -172,7 +163,6 @@ impl Prescaler { | |||||||
|  |  | ||||||
| pub struct Adc<'d, T: Instance> { | pub struct Adc<'d, T: Instance> { | ||||||
|     sample_time: SampleTime, |     sample_time: SampleTime, | ||||||
|     vref_mv: u32, |  | ||||||
|     resolution: Resolution, |     resolution: Resolution, | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut T>, | ||||||
| } | } | ||||||
| @@ -200,7 +190,6 @@ where | |||||||
|         Self { |         Self { | ||||||
|             sample_time: Default::default(), |             sample_time: Default::default(), | ||||||
|             resolution: Resolution::default(), |             resolution: Resolution::default(), | ||||||
|             vref_mv: VREF_DEFAULT_MV, |  | ||||||
|             phantom: PhantomData, |             phantom: PhantomData, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -213,18 +202,6 @@ where | |||||||
|         self.resolution = resolution; |         self.resolution = resolution; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion. |  | ||||||
|     /// |  | ||||||
|     /// Use this if you have a known precise VREF (VDDA) pin reference voltage. |  | ||||||
|     pub fn set_vref_mv(&mut self, vref_mv: u32) { |  | ||||||
|         self.vref_mv = vref_mv; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Convert a measurement to millivolts |  | ||||||
|     pub fn to_millivolts(&self, sample: u16) -> u16 { |  | ||||||
|         ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Enables internal voltage reference and returns [VrefInt], which can be used in |     /// Enables internal voltage reference and returns [VrefInt], which can be used in | ||||||
|     /// [Adc::read_internal()] to perform conversion. |     /// [Adc::read_internal()] to perform conversion. | ||||||
|     pub fn enable_vrefint(&self) -> VrefInt { |     pub fn enable_vrefint(&self) -> VrefInt { | ||||||
|   | |||||||
| @@ -205,7 +205,6 @@ pub use sample_time::SampleTime; | |||||||
|  |  | ||||||
| pub struct Adc<'d, T: Instance> { | pub struct Adc<'d, T: Instance> { | ||||||
|     sample_time: SampleTime, |     sample_time: SampleTime, | ||||||
|     vref_mv: u32, |  | ||||||
|     resolution: Resolution, |     resolution: Resolution, | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut T>, | ||||||
| } | } | ||||||
| @@ -244,7 +243,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||||||
|         Self { |         Self { | ||||||
|             sample_time: Default::default(), |             sample_time: Default::default(), | ||||||
|             resolution: Resolution::default(), |             resolution: Resolution::default(), | ||||||
|             vref_mv: VREF_DEFAULT_MV, |  | ||||||
|             phantom: PhantomData, |             phantom: PhantomData, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -285,31 +283,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||||||
|         Vbat {} |         Vbat {} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Calculates the system VDDA by sampling the internal VREFINT channel and comparing |  | ||||||
|     /// the result with the value stored at the factory. If the chip's VDDA is not stable, run |  | ||||||
|     /// this before each ADC conversion. |  | ||||||
|     #[cfg(not(stm32g0))] // TODO is this supposed to be public? |  | ||||||
|     #[allow(unused)] // TODO is this supposed to be public? |  | ||||||
|     fn calibrate(&mut self, vrefint: &mut VrefInt) { |  | ||||||
|         #[cfg(stm32l5)] |  | ||||||
|         let vrefint_cal: u32 = todo!(); |  | ||||||
|         #[cfg(not(stm32l5))] |  | ||||||
|         let vrefint_cal = unsafe { crate::pac::VREFINTCAL.data().read().value() }; |  | ||||||
|         let old_sample_time = self.sample_time; |  | ||||||
|  |  | ||||||
|         // "Table 24. Embedded internal voltage reference" states that the sample time needs to be |  | ||||||
|         // at a minimum 4 us. With 640.5 ADC cycles we have a minimum of 8 us at 80 MHz, leaving |  | ||||||
|         // some headroom. |  | ||||||
|         self.sample_time = SampleTime::Cycles640_5; |  | ||||||
|  |  | ||||||
|         // This can't actually fail, it's just in a result to satisfy hal trait |  | ||||||
|         let vrefint_samp = self.read(vrefint); |  | ||||||
|  |  | ||||||
|         self.sample_time = old_sample_time; |  | ||||||
|  |  | ||||||
|         self.vref_mv = (VREF_CALIB_MV * u32::from(vrefint_cal)) / u32::from(vrefint_samp); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pub fn set_sample_time(&mut self, sample_time: SampleTime) { |     pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||||||
|         self.sample_time = sample_time; |         self.sample_time = sample_time; | ||||||
|     } |     } | ||||||
| @@ -318,18 +291,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||||||
|         self.resolution = resolution; |         self.resolution = resolution; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion. |  | ||||||
|     /// |  | ||||||
|     /// Use this if you have a known precise VREF (VDDA) pin reference voltage. |  | ||||||
|     pub fn set_vref_mv(&mut self, vref_mv: u32) { |  | ||||||
|         self.vref_mv = vref_mv; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Convert a measurement to millivolts |  | ||||||
|     pub fn to_millivolts(&self, sample: u16) -> u16 { |  | ||||||
|         ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|     /// Convert a raw sample from the `Temperature` to deg C |     /// Convert a raw sample from the `Temperature` to deg C | ||||||
|     pub fn to_degrees_centigrade(sample: u16) -> f32 { |     pub fn to_degrees_centigrade(sample: u16) -> f32 { | ||||||
|   | |||||||
| @@ -314,7 +314,6 @@ impl Prescaler { | |||||||
|  |  | ||||||
| pub struct Adc<'d, T: Instance> { | pub struct Adc<'d, T: Instance> { | ||||||
|     sample_time: SampleTime, |     sample_time: SampleTime, | ||||||
|     vref_mv: u32, |  | ||||||
|     resolution: Resolution, |     resolution: Resolution, | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut T>, | ||||||
| } | } | ||||||
| @@ -352,7 +351,6 @@ impl<'d, T: Instance + crate::rcc::RccPeripheral> Adc<'d, T> { | |||||||
|  |  | ||||||
|         let mut s = Self { |         let mut s = Self { | ||||||
|             sample_time: Default::default(), |             sample_time: Default::default(), | ||||||
|             vref_mv: VREF_DEFAULT_MV, |  | ||||||
|             resolution: Resolution::default(), |             resolution: Resolution::default(), | ||||||
|             phantom: PhantomData, |             phantom: PhantomData, | ||||||
|         }; |         }; | ||||||
| @@ -459,18 +457,6 @@ impl<'d, T: Instance + crate::rcc::RccPeripheral> Adc<'d, T> { | |||||||
|         self.resolution = resolution; |         self.resolution = resolution; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion. |  | ||||||
|     /// |  | ||||||
|     /// Use this if you have a known precise VREF (VDDA) pin reference voltage. |  | ||||||
|     pub fn set_vref_mv(&mut self, vref_mv: u32) { |  | ||||||
|         self.vref_mv = vref_mv; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Convert a measurement to millivolts |  | ||||||
|     pub fn to_millivolts(&self, sample: u16) -> u16 { |  | ||||||
|         ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Perform a single conversion. |     /// Perform a single conversion. | ||||||
|     fn convert(&mut self) -> u16 { |     fn convert(&mut self) -> u16 { | ||||||
|         unsafe { |         unsafe { | ||||||
|   | |||||||
| @@ -17,10 +17,18 @@ async fn main(_spawner: Spawner) { | |||||||
|     let mut pin = p.PB1; |     let mut pin = p.PB1; | ||||||
|  |  | ||||||
|     let mut vref = adc.enable_vref(&mut Delay); |     let mut vref = adc.enable_vref(&mut Delay); | ||||||
|     adc.calibrate(&mut vref); |     let vref_sample = adc.read(&mut vref); | ||||||
|  |     let convert_to_millivolts = |sample| { | ||||||
|  |         // From http://www.st.com/resource/en/datasheet/CD00161566.pdf | ||||||
|  |         // 5.3.4 Embedded reference voltage | ||||||
|  |         const VREF_MV: u32 = 1200; | ||||||
|  |  | ||||||
|  |         (u32::from(sample) * VREF_MV / u32::from(vref_sample)) as u16 | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     loop { |     loop { | ||||||
|         let v = adc.read(&mut pin); |         let v = adc.read(&mut pin); | ||||||
|         info!("--> {} - {} mV", v, adc.to_millivolts(v)); |         info!("--> {} - {} mV", v, convert_to_millivolts(v)); | ||||||
|         Timer::after(Duration::from_millis(100)).await; |         Timer::after(Duration::from_millis(100)).await; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,19 +24,40 @@ async fn main(_spawner: Spawner) { | |||||||
|     // Startup delay can be combined to the maximum of either |     // Startup delay can be combined to the maximum of either | ||||||
|     delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); |     delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); | ||||||
|  |  | ||||||
|  |     let vref_sample = adc.read_internal(&mut vrefint); | ||||||
|  |  | ||||||
|  |     let convert_to_millivolts = |sample| { | ||||||
|  |         // From http://www.st.com/resource/en/datasheet/DM00071990.pdf | ||||||
|  |         // 6.3.24 Reference voltage | ||||||
|  |         const VREF_MILLIVOLTS: u32 = 1210; // mV | ||||||
|  |  | ||||||
|  |         (u32::from(sample) * VREF_MILLIVOLTS / u32::from(vref_sample)) as u16 | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     let convert_to_celcius = |sample| { | ||||||
|  |         // From http://www.st.com/resource/en/datasheet/DM00071990.pdf | ||||||
|  |         // 6.3.22 Temperature sensor characteristics | ||||||
|  |         const V25: i32 = 760; // mV | ||||||
|  |         const AVG_SLOPE: f32 = 2.5; // mV/C | ||||||
|  |  | ||||||
|  |         let sample_mv = convert_to_millivolts(sample) as i32; | ||||||
|  |  | ||||||
|  |         (sample_mv - V25) as f32 / AVG_SLOPE + 25.0 | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     loop { |     loop { | ||||||
|         // Read pin |         // Read pin | ||||||
|         let v = adc.read(&mut pin); |         let v = adc.read(&mut pin); | ||||||
|         info!("PC1: {} ({} mV)", v, adc.to_millivolts(v)); |         info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); | ||||||
|  |  | ||||||
|         // Read internal temperature |         // Read internal temperature | ||||||
|         let v = adc.read_internal(&mut temp); |         let v = adc.read_internal(&mut temp); | ||||||
|         let celcius = Temperature::to_celcius(adc.to_millivolts(v)); |         let celcius = convert_to_celcius(v); | ||||||
|         info!("Internal temp: {} ({} C)", v, celcius); |         info!("Internal temp: {} ({} C)", v, celcius); | ||||||
|  |  | ||||||
|         // Read internal voltage reference |         // Read internal voltage reference | ||||||
|         let v = adc.read_internal(&mut vrefint); |         let v = adc.read_internal(&mut vrefint); | ||||||
|         info!("VrefInt: {} ({} mV)", v, adc.to_millivolts(v)); |         info!("VrefInt: {} ({} mV)", v, convert_to_millivolts(v)); | ||||||
|  |  | ||||||
|         Timer::after(Duration::from_millis(100)).await; |         Timer::after(Duration::from_millis(100)).await; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -16,9 +16,19 @@ async fn main(_spawner: Spawner) { | |||||||
|     let mut adc = Adc::new(p.ADC1, &mut Delay); |     let mut adc = Adc::new(p.ADC1, &mut Delay); | ||||||
|     let mut pin = p.PA3; |     let mut pin = p.PA3; | ||||||
|  |  | ||||||
|  |     let mut vref = adc.enable_vrefint(); | ||||||
|  |     let vref_sample = adc.read_internal(&mut vref); | ||||||
|  |     let convert_to_millivolts = |sample| { | ||||||
|  |         // From http://www.st.com/resource/en/datasheet/DM00273119.pdf | ||||||
|  |         // 6.3.27 Reference voltage | ||||||
|  |         const VREF_MV: u32 = 1210; | ||||||
|  |  | ||||||
|  |         (u32::from(sample) * VREF_MV / u32::from(vref_sample)) as u16 | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     loop { |     loop { | ||||||
|         let v = adc.read(&mut pin); |         let v = adc.read(&mut pin); | ||||||
|         info!("--> {} - {} mV", v, adc.to_millivolts(v)); |         info!("--> {} - {} mV", v, convert_to_millivolts(v)); | ||||||
|         Timer::after(Duration::from_millis(100)).await; |         Timer::after(Duration::from_millis(100)).await; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user