summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/adc.c8
-rw-r--r--ports/stm32/adc.h31
-rw-r--r--ports/stm32/boards/stm32f4xx_hal_conf_base.h1
-rw-r--r--ports/stm32/boards/stm32f7xx_hal_conf_base.h1
-rw-r--r--ports/stm32/machine_adc.c8
5 files changed, 43 insertions, 6 deletions
diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c
index 3793ef5ff..5fa22d7c7 100644
--- a/ports/stm32/adc.c
+++ b/ports/stm32/adc.c
@@ -380,16 +380,14 @@ STATIC uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32
adc_config_channel(adcHandle, channel);
uint32_t raw_value = adc_read_channel(adcHandle);
- #if defined(STM32F4) || defined(STM32F7)
// ST docs say that (at least on STM32F42x and STM32F43x), VBATE must
// be disabled when TSVREFE is enabled for TEMPSENSOR and VREFINT
// conversions to work. VBATE is enabled by the above call to read
// the channel, and here we disable VBATE so a subsequent call for
// TEMPSENSOR or VREFINT works correctly.
- if (channel == ADC_CHANNEL_VBAT) {
- ADC->CCR &= ~ADC_CCR_VBATE;
- }
- #endif
+ // It's also good to disable the VBAT switch to prevent battery drain,
+ // so disable it for all MCUs.
+ adc_deselect_vbat(adcHandle->Instance, channel);
return raw_value;
}
diff --git a/ports/stm32/adc.h b/ports/stm32/adc.h
index 4ae6022bc..6f2e61e09 100644
--- a/ports/stm32/adc.h
+++ b/ports/stm32/adc.h
@@ -29,4 +29,35 @@
extern const mp_obj_type_t pyb_adc_type;
extern const mp_obj_type_t pyb_adc_all_type;
+#if defined(ADC_CHANNEL_VBAT)
+
+static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) {
+ (void)adc;
+
+ if (channel == ADC_CHANNEL_VBAT) {
+ ADC_Common_TypeDef *adc_common;
+
+ #if defined(STM32F0) || defined(STM32WB)
+ adc_common = ADC1_COMMON;
+ #elif defined(STM32F4) || defined(STM32L4)
+ adc_common = ADC_COMMON_REGISTER(0);
+ #elif defined(STM32F7)
+ adc_common = ADC123_COMMON;
+ #elif defined(STM32H7)
+ adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON;
+ #endif
+
+ adc_common->CCR &= ~LL_ADC_PATH_INTERNAL_VBAT;
+ }
+}
+
+#else
+
+static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) {
+ (void)adc;
+ (void)channel;
+}
+
+#endif
+
#endif // MICROPY_INCLUDED_STM32_ADC_H
diff --git a/ports/stm32/boards/stm32f4xx_hal_conf_base.h b/ports/stm32/boards/stm32f4xx_hal_conf_base.h
index 8d8bb8f4e..91f064835 100644
--- a/ports/stm32/boards/stm32f4xx_hal_conf_base.h
+++ b/ports/stm32/boards/stm32f4xx_hal_conf_base.h
@@ -53,6 +53,7 @@
#include "stm32f4xx_hal_uart.h"
#include "stm32f4xx_hal_usart.h"
#include "stm32f4xx_hal_wwdg.h"
+#include "stm32f4xx_ll_adc.h"
#include "stm32f4xx_ll_rtc.h"
// Enable various HAL modules
diff --git a/ports/stm32/boards/stm32f7xx_hal_conf_base.h b/ports/stm32/boards/stm32f7xx_hal_conf_base.h
index 83a144f8f..1a3fca3ac 100644
--- a/ports/stm32/boards/stm32f7xx_hal_conf_base.h
+++ b/ports/stm32/boards/stm32f7xx_hal_conf_base.h
@@ -53,6 +53,7 @@
#include "stm32f7xx_hal_uart.h"
#include "stm32f7xx_hal_usart.h"
#include "stm32f7xx_hal_wwdg.h"
+#include "stm32f7xx_ll_adc.h"
#include "stm32f7xx_ll_rtc.h"
// Enable various HAL modules
diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c
index 9c20f0f95..d9e5a64da 100644
--- a/ports/stm32/machine_adc.c
+++ b/ports/stm32/machine_adc.c
@@ -26,6 +26,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#include "adc.h"
#if defined(STM32F0) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
#define ADC_V2 (1)
@@ -335,10 +336,15 @@ STATIC uint32_t adc_config_and_read_u16(ADC_TypeDef *adc, uint32_t channel, uint
return 0xffff;
}
+ // Select, configure and read the channel.
adc_config_channel(adc, channel, sample_time);
uint32_t raw = adc_read_channel(adc);
+
+ // If VBAT was sampled then deselect it to prevent battery drain.
+ adc_deselect_vbat(adc, channel);
+
+ // Scale raw reading to 16 bit value using a Taylor expansion (for bits <= 16).
uint32_t bits = adc_get_bits(adc);
- // Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16)
#if defined(STM32H7)
if (bits < 8) {
// For 6 and 7 bits