Browse Source

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

Signed-off-by: Damien George <damien@micropython.org>
pull/6702/head
Damien George 4 years ago
parent
commit
80883a82c0
  1. 8
      ports/stm32/adc.c
  2. 31
      ports/stm32/adc.h
  3. 1
      ports/stm32/boards/stm32f4xx_hal_conf_base.h
  4. 1
      ports/stm32/boards/stm32f7xx_hal_conf_base.h
  5. 8
      ports/stm32/machine_adc.c

8
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;
}

31
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

1
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

1
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

8
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

Loading…
Cancel
Save