Merge pull request #6987 from jeromecoutant/PR_ADC

STM32 ADC update
pull/7094/head
Cruz Monrreal 2018-06-02 19:52:51 -05:00 committed by GitHub
commit 07fb7c1adc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 160 additions and 66 deletions

View File

@ -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, ...)
@ -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)) {
HAL_ADCEx_Calibration_Start(&obj->handle);
}
}
@ -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:
@ -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:

View File

@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal_def.h"
/* Include low level driver */
#include "stm32f0xx_ll_adc.h"
/** @addtogroup STM32F0xx_HAL_Driver
* @{
*/

View File

@ -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, ...)
@ -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
@ -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:
@ -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;

View File

@ -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) {
@ -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;

View File

@ -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, ...)
@ -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);
}
}
@ -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;

View File

@ -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
* @{
*/

View File

@ -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);
/* 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))
@ -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;
}
}
}

View File

@ -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;

View File

@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/* Include low level driver */
#include "stm32f4xx_ll_adc.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/

View File

@ -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). */
/**
* @}
*/
@ -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)

View File

@ -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) {
@ -161,17 +161,26 @@ 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;
}
// Measuring VBAT sets the ADC_CCR_VBATE bit in ADC->CCR, and there is not
// possibility with the ST HAL driver to clear it. If it isn't cleared,
// VBAT remains connected to the ADC channel in preference to temperature,
// so VBAT readings are returned in place of temperature.
ADC->CCR &= ~(ADC_CCR_VBATE | ADC_CCR_TSVREFE);
HAL_ADC_ConfigChannel(&obj->handle, &sConfig);
HAL_ADC_Start(&obj->handle); // Start conversion

View File

@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f7xx_hal_def.h"
/* Include low level driver */
#include "stm32f7xx_ll_adc.h"
/** @addtogroup STM32F7xx_HAL_Driver
* @{
*/

View File

@ -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, ...)
@ -92,9 +90,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 (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) {
HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
}
@ -171,7 +167,9 @@ uint16_t adc_read(analogin_t *obj)
return 0;
}
ADC1->CHSELR = 0; // [TODO] Workaround. To be removed after Cube driver is corrected.
/* Reset ADC channel selection register */
ADC1->CHSELR = 0;
HAL_ADC_ConfigChannel(&obj->handle, &sConfig);
HAL_ADC_Start(&obj->handle); // Start conversion

View File

@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32l0xx_hal_def.h"
/* Include low level driver */
#include "stm32l0xx_ll_adc.h"
/** @addtogroup STM32L0xx_HAL_Driver
* @{
*/

View File

@ -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_hsi_inited = false;
RCC_OscInitTypeDef RCC_OscInitStruct;
uint32_t function = (uint32_t)NC;
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
@ -92,10 +89,9 @@ void analogin_init(analogin_t *obj, PinName pin)
error("Cannot initialize ADC");
}
// This section is done only once
if (!adc_hsi_inited) {
adc_hsi_inited = true;
if (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY)) {
// Enable the HSI (to clock the ADC)
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

View File

@ -44,6 +44,9 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32l1xx_hal_def.h"
/* Include low level driver */
#include "stm32l1xx_ll_adc.h"
/** @addtogroup STM32L1xx_HAL_Driver
* @{
*/

View File

@ -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, ...)
@ -94,8 +92,7 @@ void analogin_init(analogin_t *obj, PinName pin)
}
// 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);
}
}