From 072ec2e76564121c5a27dfe7db6ccf853eceaf8f Mon Sep 17 00:00:00 2001 From: bcostm Date: Tue, 14 Nov 2017 15:27:41 +0100 Subject: [PATCH] STM32L4 ADC: remove adc_inited flag --- .../TARGET_STM/TARGET_STM32L4/analogin_api.c | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/analogin_api.c b/targets/TARGET_STM/TARGET_STM32L4/analogin_api.c index 9fc5e1ff00..c162604caf 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/analogin_api.c +++ b/targets/TARGET_STM/TARGET_STM32L4/analogin_api.c @@ -36,10 +36,9 @@ #include "mbed_error.h" #include "PeripheralPins.h" -int adc_inited = 0; - void analogin_init(analogin_t *obj, PinName pin) { + static int adc_calibrated = 0; uint32_t function = (uint32_t)NC; // ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...) @@ -48,14 +47,14 @@ void analogin_init(analogin_t *obj, PinName pin) if ((pin < 0xF0) || (pin >= 0x100)) { // Normal channels // Get the peripheral name from the pin and assign it to the object - obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC); + obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC); // Get the functions (adc channel) from the pin and assign it to the object function = pinmap_function(pin, PinMap_ADC); // Configure GPIO pinmap_pinout(pin, PinMap_ADC); } else { // Internal channels - obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC_Internal); + obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal); function = pinmap_function(pin, PinMap_ADC_Internal); // No GPIO configuration for internal channels } @@ -67,37 +66,35 @@ void analogin_init(analogin_t *obj, PinName pin) // Save pin number for the read function obj->pin = pin; - // The ADC initialization is done once - if (adc_inited == 0) { - adc_inited = 1; + // Configure ADC object structures + obj->handle.State = HAL_ADC_STATE_RESET; + obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // Asynchronous clock mode, input ADC clock + obj->handle.Init.Resolution = ADC_RESOLUTION_12B; + obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; + obj->handle.Init.ScanConvMode = DISABLE; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) + obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // On STM32L1xx ADC, overrun detection is enabled only if EOC selection is set to each conversion (or transfer by DMA enabled, this is not the case in this example). + obj->handle.Init.LowPowerAutoWait = DISABLE; + obj->handle.Init.ContinuousConvMode = DISABLE; // Continuous mode disabled to have only 1 conversion at each conversion trig + obj->handle.Init.NbrOfConversion = 1; // Parameter discarded because sequencer is disabled + obj->handle.Init.DiscontinuousConvMode = DISABLE; // Parameter discarded because sequencer is disabled + obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled + obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Software start to trig the 1st conversion manually, without external event + obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + obj->handle.Init.DMAContinuousRequests = DISABLE; + obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // DR register is overwritten with the last conversion result in case of overrun + obj->handle.Init.OversamplingMode = DISABLE; // No oversampling - // Enable ADC clock - __HAL_RCC_ADC_CLK_ENABLE(); - __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); + // Enable ADC clock + __HAL_RCC_ADC_CLK_ENABLE(); + __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); - obj->handle.State = HAL_ADC_STATE_RESET; - // Configure ADC - obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // Asynchronous clock mode, input ADC clock - obj->handle.Init.Resolution = ADC_RESOLUTION_12B; - obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; - obj->handle.Init.ScanConvMode = DISABLE; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) - obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // On STM32L1xx ADC, overrun detection is enabled only if EOC selection is set to each conversion (or transfer by DMA enabled, this is not the case in this example). - obj->handle.Init.LowPowerAutoWait = DISABLE; - obj->handle.Init.ContinuousConvMode = DISABLE; // Continuous mode disabled to have only 1 conversion at each conversion trig - obj->handle.Init.NbrOfConversion = 1; // Parameter discarded because sequencer is disabled - obj->handle.Init.DiscontinuousConvMode = DISABLE; // Parameter discarded because sequencer is disabled - obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled - obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Software start to trig the 1st conversion manually, without external event - obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - obj->handle.Init.DMAContinuousRequests = DISABLE; - obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // DR register is overwritten with the last conversion result in case of overrun - obj->handle.Init.OversamplingMode = DISABLE; // No oversampling + if (HAL_ADC_Init(&obj->handle) != HAL_OK) { + error("Cannot initialize ADC"); + } - if (HAL_ADC_Init(&obj->handle) != HAL_OK) { - error("Cannot initialize ADC\n"); - } - - // Calibrate ADC + // ADC calibration is done only once + if (adc_calibrated == 0) { + adc_calibrated = 1; HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED); } } @@ -181,7 +178,7 @@ static inline uint16_t adc_read(analogin_t *obj) // Wait end of conversion and get value if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) { - return (HAL_ADC_GetValue(&obj->handle)); + return (uint16_t)HAL_ADC_GetValue(&obj->handle); } else { return 0; }