From 079c5aaf0c4f8f3d546f9df02fa592c85cad7659 Mon Sep 17 00:00:00 2001 From: Nathan Fox Date: Sun, 24 Apr 2022 21:15:47 -0400 Subject: [PATCH] add temp/vref controls --- CHANGELOG.md | 2 ++ src/adc.rs | 53 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe75bcbf..d3ffd694 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `Serial` support for UART4/5 - Allow to set HSE bypass bit in `RCC` clock configuration register to use an external clock input on the `OSC_IN` pin [#485] - initial support of `embedded-hal-1.0` [#416] +- Added ADC methods for temp/vref sensor control. The time required for reading from the ADC can be reduced using these [#422] - Add tools/check.py python script for local check [#467] - Add changelog check on PRs [#467] - Reexport `Direction` from `qei` [#479] @@ -59,6 +60,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add enable/disable EOC interrupt functions for ADCs [#526] [#416]: https://github.com/stm32-rs/stm32f1xx-hal/pull/416 +[#422]: https://github.com/stm32-rs/stm32f1xx-hal/pull/422 [#453]: https://github.com/stm32-rs/stm32f1xx-hal/pull/453 [#462]: https://github.com/stm32-rs/stm32f1xx-hal/pull/462 [#467]: https://github.com/stm32-rs/stm32f1xx-hal/pull/467 diff --git a/src/adc.rs b/src/adc.rs index d7602cde..05ac87a6 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -18,6 +18,9 @@ use embedded_dma::WriteBuffer; use crate::pac::{self, RCC}; use crate::pacext::adc::{AdcRB, Cr1W, Cr2R, Cr2W, Dr, ExtSelW}; +const TEMP_CHANNEL: u8 = 16; +const VREF_CHANNEL: u8 = 17; + /// Continuous mode pub struct Continuous; /// Scan mode @@ -497,7 +500,25 @@ where impl Adc { fn read_aux(&mut self, chan: u8) -> u16 { - let tsv_off = if self.rb.cr2().read().tsvrefe().bit_is_clear() { + let tsv_enabled = matches!(chan, TEMP_CHANNEL | VREF_CHANNEL) && self.enable_temp_vref(); + + let val = self.convert(chan); + + if tsv_enabled { + self.disable_temp_vref(); + } + + val + } + + /// Enables the temperature / VREF sensor. + /// + /// Enabling this before calling `read_temp` or `read_vref` will speed up the reading + /// since you won't have to wait for the sensor to start up. + /// + /// Returns true if the sensor was previously off. + pub fn enable_temp_vref(&mut self) -> bool { + if !self.is_temp_vref_enabled() { self.rb.cr2().modify(|_, w| w.tsvrefe().set_bit()); // The reference manual says that a stabilization time is needed after the powering the @@ -508,15 +529,19 @@ impl Adc { true } else { false - }; - - let val = self.convert(chan); - - if tsv_off { - self.rb.cr2().modify(|_, w| w.tsvrefe().clear_bit()); } + } - val + /// Disables the temperature / VREF sensor. + /// + /// `read_temp` and `read_vref` will still work with this disabled, but will take a + /// bit longer since you have to wait for the sensor to start up. + pub fn disable_temp_vref(&mut self) { + self.rb.cr2().modify(|_, w| w.tsvrefe().clear_bit()); + } + + pub fn is_temp_vref_enabled(&self) -> bool { + self.rb.cr2().read().tsvrefe().bit_is_set() } /// Temperature sensor is connected to channel 16 on ADC1. This sensor can be used @@ -531,6 +556,9 @@ impl Adc { /// temperature readings are needed, an external temperature sensor part should be used." /// /// Formula to calculate temperature value is also taken from the section 11.10. + /// + /// If the temp/VREF sensor is disabled, this will still work but must wait + /// for the sensor to start up. Call `enable_temp_vref` to speed this up. pub fn read_temp(&mut self) -> i32 { /// According to section 5.3.18 "Temperature sensor characteristics" /// from STM32F1xx datasheets, TS constants values are as follows: @@ -556,8 +584,8 @@ impl Adc { }; self.set_sample_time(sample_time); - let val_temp: i32 = self.read_aux(16u8).into(); - let val_vref: i32 = self.read_aux(17u8).into(); + let val_temp: i32 = self.read_aux(TEMP_CHANNEL).into(); + let val_vref: i32 = self.read_aux(VREF_CHANNEL).into(); let v_sense = val_temp * 1200 / val_vref; self.restore_cfg(prev_cfg); @@ -573,8 +601,11 @@ impl Adc { /// For instance, reading from any ADC channel can be converted into voltage (mV) /// using the following formula: /// v_chan = adc.read(chan) * 1200 / adc.read_vref() + /// + /// If the temp/VREF sensor is disabled, this will still work but must wait + /// for the sensor to start up. Call `enable_temp_vref` to speed this up. pub fn read_vref(&mut self) -> u16 { - self.read_aux(17u8) + self.read_aux(VREF_CHANNEL) } }