Skip to content

stm32/adc: Deselect VBAT after reading to prevent battery drain. #6702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions ports/stm32/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
31 changes: 31 additions & 0 deletions ports/stm32/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions ports/stm32/boards/stm32f4xx_hal_conf_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions ports/stm32/boards/stm32f7xx_hal_conf_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion ports/stm32/machine_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down