Skip to content

STM32 ADC update #6987

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 9 commits into from
Jun 3, 2018
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
15 changes: 5 additions & 10 deletions targets/TARGET_STM/TARGET_STM32F0/analogin_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@
#include "pinmap.h"
#include "mbed_error.h"
#include "PeripheralPins.h"
#include <stdbool.h>

void analogin_init(analogin_t *obj, PinName pin)
{
static bool adc_calibrated = false;
uint32_t function = (uint32_t)NC;

// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
Expand Down Expand Up @@ -89,9 +87,7 @@ void analogin_init(analogin_t *obj, PinName pin)
error("Cannot initialize ADC");
}

// ADC calibration is done only once
if (!adc_calibrated) {
adc_calibrated = true;
if (!LL_ADC_REG_ReadConversionData6(obj->handle.Instance)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how this macro can determine if the calibration has been done or not ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check RM:
ADC data register (ADC_DR)
Just after a calibration is complete, DATA[6:0] contains the calibration factor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

HAL_ADCEx_Calibration_Start(&obj->handle);
}
}
Expand All @@ -102,11 +98,7 @@ uint16_t adc_read(analogin_t *obj)

// Configure ADC channel
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
#if defined (TARGET_STM32F091RC)
sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
#else
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
#endif
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;

switch (obj->channel) {
case 0:
Expand Down Expand Up @@ -159,13 +151,16 @@ uint16_t adc_read(analogin_t *obj)
break;
case 16:
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
break;
case 17:
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
break;
#ifdef ADC_CHANNEL_VBAT
case 18:
sConfig.Channel = ADC_CHANNEL_VBAT;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
break;
#endif
default:
Expand Down
3 changes: 3 additions & 0 deletions targets/TARGET_STM/TARGET_STM32F0/device/stm32f0xx_hal_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal_def.h"

/* Include low level driver */
#include "stm32f0xx_ll_adc.h"

/** @addtogroup STM32F0xx_HAL_Driver
* @{
*/
Expand Down
11 changes: 5 additions & 6 deletions targets/TARGET_STM/TARGET_STM32F1/analogin_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@
#include "pinmap.h"
#include "mbed_error.h"
#include "PeripheralPins.h"
#include <stdbool.h>

void analogin_init(analogin_t *obj, PinName pin)
{
static bool adc_calibrated = false;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
uint32_t function = (uint32_t)NC;

// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
Expand Down Expand Up @@ -86,8 +83,8 @@ void analogin_init(analogin_t *obj, PinName pin)
}

// This section is done only once
if (!adc_calibrated) {
adc_calibrated = true;
if (__HAL_RCC_GET_ADC_SOURCE() != RCC_ADCPCLK2_DIV6) {
RCC_PeriphCLKInitTypeDef PeriphClkInit;
// Configure ADC clock prescaler
// Caution: On STM32F1, ADC clock frequency max is 14 MHz (refer to device datasheet).
// Therefore, ADC clock prescaler must be configured in function
Expand All @@ -108,7 +105,7 @@ uint16_t adc_read(analogin_t *obj)

// Configure ADC channel
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;

switch (obj->channel) {
case 0:
Expand Down Expand Up @@ -161,9 +158,11 @@ uint16_t adc_read(analogin_t *obj)
break;
case 16:
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
break;
case 17:
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
break;
default:
return 0;
Expand Down
5 changes: 4 additions & 1 deletion targets/TARGET_STM/TARGET_STM32F2/analogin_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ uint16_t adc_read(analogin_t *obj)

// Configure ADC channel
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
sConfig.Offset = 0;

switch (obj->channel) {
Expand Down Expand Up @@ -161,12 +161,15 @@ uint16_t adc_read(analogin_t *obj)
break;
case 16:
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
break;
case 17:
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
break;
case 18:
sConfig.Channel = ADC_CHANNEL_VBAT;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
break;
default:
return 0;
Expand Down
47 changes: 37 additions & 10 deletions targets/TARGET_STM/TARGET_STM32F3/analogin_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@
#include "pinmap.h"
#include "mbed_error.h"
#include "PeripheralPins.h"
#include <stdbool.h>

void analogin_init(analogin_t *obj, PinName pin)
{
static bool adc_calibrated = false;
uint32_t function = (uint32_t)NC;

// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
Expand Down Expand Up @@ -106,12 +104,10 @@ void analogin_init(analogin_t *obj, PinName pin)
#endif

if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
error("Cannot initialize ADC");
error("Cannot initialize ADC\n");
}

// ADC calibration is done only once
if (!adc_calibrated) {
adc_calibrated = true;
if (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) {
HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
}
}
Expand Down Expand Up @@ -171,16 +167,47 @@ uint16_t adc_read(analogin_t *obj)
sConfig.Channel = ADC_CHANNEL_14;
break;
case 15:
sConfig.Channel = ADC_CHANNEL_15;
if ((ADCName)obj->handle.Instance == ADC_1) {
sConfig.Channel = ADC_CHANNEL_VOPAMP1;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
}
else {
sConfig.Channel = ADC_CHANNEL_15;
}
break;
case 16:
sConfig.Channel = ADC_CHANNEL_16;
if ((ADCName)obj->handle.Instance == ADC_1) {
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
}
else {
sConfig.Channel = ADC_CHANNEL_16;
}
break;
case 17:
sConfig.Channel = ADC_CHANNEL_17;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
if ((ADCName)obj->handle.Instance == ADC_1) {
sConfig.Channel = ADC_CHANNEL_VBAT;
}
#if defined(ADC2)
if ((ADCName)obj->handle.Instance == ADC_2) {
sConfig.Channel = ADC_CHANNEL_VOPAMP2;
}
#endif
#if defined(ADC3)
if ((ADCName)obj->handle.Instance == ADC_3) {
sConfig.Channel = ADC_CHANNEL_VOPAMP3;
}
#endif
#if defined(ADC4)
if ((ADCName)obj->handle.Instance == ADC_4) {
sConfig.Channel = ADC_CHANNEL_VOPAMP4;
}
#endif
break;
case 18:
sConfig.Channel = ADC_CHANNEL_18;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
sConfig.Channel = ADC_CHANNEL_VREFINT;
break;
default:
return 0;
Expand Down
5 changes: 4 additions & 1 deletion targets/TARGET_STM/TARGET_STM32F3/device/stm32f3xx_hal_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@
/* Include ADC HAL Extended module */
/* (include on top of file since ADC structures are defined in extended file) */
#include "stm32f3xx_hal_adc_ex.h"


/* Include low level driver */
#include "stm32f3xx_ll_adc.h"

/** @addtogroup STM32F3xx_HAL_Driver
* @{
*/
Expand Down
17 changes: 0 additions & 17 deletions targets/TARGET_STM/TARGET_STM32F3/device/stm32f3xx_hal_adc_ex.c
Original file line number Diff line number Diff line change
Expand Up @@ -5660,12 +5660,6 @@ HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConf
/* Set handle of the other ADC sharing the same common register */
ADC_COMMON_ADC_OTHER(hadc, &tmphadcSharingSameCommonRegister);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it removed ? Is it a patch that we have added previously ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, same kind of patch as #6412

/* Software is allowed to change common parameters only when all ADCs */
/* of the common group are disabled. */
if ((ADC_IS_ENABLE(hadc) == RESET) &&
( (tmphadcSharingSameCommonRegister.Instance == NULL) ||
(ADC_IS_ENABLE(&tmphadcSharingSameCommonRegister) == RESET) ) )
{
/* If Channel_16 is selected, enable Temp. sensor measurement path */
/* Note: Temp. sensor internal channels available on ADC1 only */
if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && (hadc->Instance == ADC1))
Expand Down Expand Up @@ -5694,17 +5688,6 @@ HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConf
{
SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);
}
}
/* If the requested internal measurement path has already been */
/* enabled and other ADC of the common group are enabled, internal */
/* measurement paths cannot be enabled. */
else
{
/* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

tmp_hal_status = HAL_ERROR;
}
}

}
Expand Down
7 changes: 3 additions & 4 deletions targets/TARGET_STM/TARGET_STM32F4/analogin_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,15 @@ uint16_t adc_read(analogin_t *obj)
break;
case 16:
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the temperature is 10us
break;
case 17:
sConfig.Channel = ADC_CHANNEL_VREFINT;
/* From experiment, measurement needs max sampling time to be valid */
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the internal reference voltage is 10us
break;
case 18:
sConfig.Channel = ADC_CHANNEL_VBAT;
/* From experiment, measurement needs max sampling time to be valid */
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the VBAT is 5us
break;
default:
return 0;
Expand Down
3 changes: 3 additions & 0 deletions targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_hal_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"

/* Include low level driver */
#include "stm32f4xx_ll_adc.h"

/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
Expand Down
70 changes: 70 additions & 0 deletions targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_ll_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ extern "C" {
/* ADC registers bits positions */
#define ADC_CR1_RES_BITOFFSET_POS (24U) /* Value equivalent to POSITION_VAL(ADC_CR1_RES) */
#define ADC_TR_HT_BITOFFSET_POS (16U) /* Value equivalent to POSITION_VAL(ADC_TR_HT) */

/* ADC internal channels related definitions */
/* Internal voltage reference VrefInt */
#define VREFINT_CAL_ADDR ((uint16_t*) (0x1FFF7A2AU)) /* Internal voltage reference, address of parameter VREFINT_CAL: VrefInt ADC raw data acquired at temperature 30 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */
#define VREFINT_CAL_VREF ( 3300U) /* Analog voltage reference (Vref+) value with which temperature sensor has been calibrated in production (tolerance: +-10 mV) (unit: mV). */
/* Temperature sensor */
#define TEMPSENSOR_CAL1_ADDR ((uint16_t*) (0x1FFF7A2CU)) /* Internal temperature sensor, address of parameter TS_CAL1: On STM32F4, temperature sensor ADC raw data acquired at temperature 30 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */
#define TEMPSENSOR_CAL2_ADDR ((uint16_t*) (0x1FFF7A2EU)) /* Internal temperature sensor, address of parameter TS_CAL2: On STM32F4, temperature sensor ADC raw data acquired at temperature 110 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */
#define TEMPSENSOR_CAL1_TEMP (( int32_t) 30) /* Internal temperature sensor, temperature at which temperature sensor has been calibrated in production for data into TEMPSENSOR_CAL1_ADDR (tolerance: +-5 DegC) (unit: DegC). */
#define TEMPSENSOR_CAL2_TEMP (( int32_t) 110) /* Internal temperature sensor, temperature at which temperature sensor has been calibrated in production for data into TEMPSENSOR_CAL2_ADDR (tolerance: +-5 DegC) (unit: DegC). */
#define TEMPSENSOR_CAL_VREFANALOG ( 3300U) /* Analog voltage reference (Vref+) voltage with which temperature sensor has been calibrated in production (+-10 mV) (unit: mV). */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add this ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To align with other STM32 families,
and be able to execute application like the one in #6398

/**
* @}
*/
Expand Down Expand Up @@ -1654,6 +1666,64 @@ typedef struct
/ __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__) \
)

/**
* @brief Helper macro to calculate the temperature (unit: degree Celsius)
* from ADC conversion data of internal temperature sensor.
* @note Computation is using temperature sensor calibration values
* stored in system memory for each device during production.
* @note Calculation formula:
* Temperature = ((TS_ADC_DATA - TS_CAL1)
* * (TS_CAL2_TEMP - TS_CAL1_TEMP))
* / (TS_CAL2 - TS_CAL1) + TS_CAL1_TEMP
* with TS_ADC_DATA = temperature sensor raw data measured by ADC
* Avg_Slope = (TS_CAL2 - TS_CAL1)
* / (TS_CAL2_TEMP - TS_CAL1_TEMP)
* TS_CAL1 = equivalent TS_ADC_DATA at temperature
* TEMP_DEGC_CAL1 (calibrated in factory)
* TS_CAL2 = equivalent TS_ADC_DATA at temperature
* TEMP_DEGC_CAL2 (calibrated in factory)
* Caution: Calculation relevancy under reserve that calibration
* parameters are correct (address and data).
* To calculate temperature using temperature sensor
* datasheet typical values (generic values less, therefore
* less accurate than calibrated values),
* use helper macro @ref __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS().
* @note As calculation input, the analog reference voltage (Vref+) must be
* defined as it impacts the ADC LSB equivalent voltage.
* @note Analog reference voltage (Vref+) must be either known from
* user board environment or can be calculated using ADC measurement
* and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE().
* @note On this STM32 serie, calibration data of temperature sensor
* corresponds to a resolution of 12 bits,
* this is the recommended ADC resolution to convert voltage of
* temperature sensor.
* Otherwise, this macro performs the processing to scale
* ADC conversion data to 12 bits.
* @param __VREFANALOG_VOLTAGE__ Analog reference voltage (unit: mV)
* @param __TEMPSENSOR_ADC_DATA__ ADC conversion data of internal
* temperature sensor (unit: digital value).
* @param __ADC_RESOLUTION__ ADC resolution at which internal temperature
* sensor voltage has been measured.
* This parameter can be one of the following values:
* @arg @ref LL_ADC_RESOLUTION_12B
* @arg @ref LL_ADC_RESOLUTION_10B
* @arg @ref LL_ADC_RESOLUTION_8B
* @arg @ref LL_ADC_RESOLUTION_6B
* @retval Temperature (unit: degree Celsius)
*/
#define __LL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\
__TEMPSENSOR_ADC_DATA__,\
__ADC_RESOLUTION__) \
(((( ((int32_t)((__LL_ADC_CONVERT_DATA_RESOLUTION((__TEMPSENSOR_ADC_DATA__), \
(__ADC_RESOLUTION__), \
LL_ADC_RESOLUTION_12B) \
* (__VREFANALOG_VOLTAGE__)) \
/ TEMPSENSOR_CAL_VREFANALOG) \
- (int32_t) *TEMPSENSOR_CAL1_ADDR) \
) * (int32_t)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP) \
) / (int32_t)((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) \
) + TEMPSENSOR_CAL1_TEMP \
)

/**
* @brief Helper macro to calculate the temperature (unit: degree Celsius)
Expand Down
Loading