Skip to content

Commit 07fb7c1

Browse files
author
Cruz Monrreal
authored
Merge pull request #6987 from jeromecoutant/PR_ADC
STM32 ADC update
2 parents 8c26e46 + 7fd4203 commit 07fb7c1

File tree

17 files changed

+160
-66
lines changed

17 files changed

+160
-66
lines changed

targets/TARGET_STM/TARGET_STM32F0/analogin_device.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,9 @@
3535
#include "pinmap.h"
3636
#include "mbed_error.h"
3737
#include "PeripheralPins.h"
38-
#include <stdbool.h>
3938

4039
void analogin_init(analogin_t *obj, PinName pin)
4140
{
42-
static bool adc_calibrated = false;
4341
uint32_t function = (uint32_t)NC;
4442

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

92-
// ADC calibration is done only once
93-
if (!adc_calibrated) {
94-
adc_calibrated = true;
90+
if (!LL_ADC_REG_ReadConversionData6(obj->handle.Instance)) {
9591
HAL_ADCEx_Calibration_Start(&obj->handle);
9692
}
9793
}
@@ -102,11 +98,7 @@ uint16_t adc_read(analogin_t *obj)
10298

10399
// Configure ADC channel
104100
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
105-
#if defined (TARGET_STM32F091RC)
106-
sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
107-
#else
108-
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
109-
#endif
101+
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
110102

111103
switch (obj->channel) {
112104
case 0:
@@ -159,13 +151,16 @@ uint16_t adc_read(analogin_t *obj)
159151
break;
160152
case 16:
161153
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
154+
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
162155
break;
163156
case 17:
164157
sConfig.Channel = ADC_CHANNEL_VREFINT;
158+
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
165159
break;
166160
#ifdef ADC_CHANNEL_VBAT
167161
case 18:
168162
sConfig.Channel = ADC_CHANNEL_VBAT;
163+
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
169164
break;
170165
#endif
171166
default:

targets/TARGET_STM/TARGET_STM32F0/device/stm32f0xx_hal_adc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
/* Includes ------------------------------------------------------------------*/
4545
#include "stm32f0xx_hal_def.h"
4646

47+
/* Include low level driver */
48+
#include "stm32f0xx_ll_adc.h"
49+
4750
/** @addtogroup STM32F0xx_HAL_Driver
4851
* @{
4952
*/

targets/TARGET_STM/TARGET_STM32F1/analogin_device.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@
3535
#include "pinmap.h"
3636
#include "mbed_error.h"
3737
#include "PeripheralPins.h"
38-
#include <stdbool.h>
3938

4039
void analogin_init(analogin_t *obj, PinName pin)
4140
{
42-
static bool adc_calibrated = false;
43-
RCC_PeriphCLKInitTypeDef PeriphClkInit;
4441
uint32_t function = (uint32_t)NC;
4542

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

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

109106
// Configure ADC channel
110107
sConfig.Rank = 1;
111-
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
108+
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
112109

113110
switch (obj->channel) {
114111
case 0:
@@ -161,9 +158,11 @@ uint16_t adc_read(analogin_t *obj)
161158
break;
162159
case 16:
163160
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
161+
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
164162
break;
165163
case 17:
166164
sConfig.Channel = ADC_CHANNEL_VREFINT;
165+
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
167166
break;
168167
default:
169168
return 0;

targets/TARGET_STM/TARGET_STM32F2/analogin_device.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ uint16_t adc_read(analogin_t *obj)
107107

108108
// Configure ADC channel
109109
sConfig.Rank = 1;
110-
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
110+
sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
111111
sConfig.Offset = 0;
112112

113113
switch (obj->channel) {
@@ -161,12 +161,15 @@ uint16_t adc_read(analogin_t *obj)
161161
break;
162162
case 16:
163163
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
164+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
164165
break;
165166
case 17:
166167
sConfig.Channel = ADC_CHANNEL_VREFINT;
168+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
167169
break;
168170
case 18:
169171
sConfig.Channel = ADC_CHANNEL_VBAT;
172+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
170173
break;
171174
default:
172175
return 0;

targets/TARGET_STM/TARGET_STM32F3/analogin_device.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,9 @@
3535
#include "pinmap.h"
3636
#include "mbed_error.h"
3737
#include "PeripheralPins.h"
38-
#include <stdbool.h>
3938

4039
void analogin_init(analogin_t *obj, PinName pin)
4140
{
42-
static bool adc_calibrated = false;
4341
uint32_t function = (uint32_t)NC;
4442

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

108106
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
109-
error("Cannot initialize ADC");
107+
error("Cannot initialize ADC\n");
110108
}
111109

112-
// ADC calibration is done only once
113-
if (!adc_calibrated) {
114-
adc_calibrated = true;
110+
if (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) {
115111
HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
116112
}
117113
}
@@ -171,16 +167,47 @@ uint16_t adc_read(analogin_t *obj)
171167
sConfig.Channel = ADC_CHANNEL_14;
172168
break;
173169
case 15:
174-
sConfig.Channel = ADC_CHANNEL_15;
170+
if ((ADCName)obj->handle.Instance == ADC_1) {
171+
sConfig.Channel = ADC_CHANNEL_VOPAMP1;
172+
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
173+
}
174+
else {
175+
sConfig.Channel = ADC_CHANNEL_15;
176+
}
175177
break;
176178
case 16:
177-
sConfig.Channel = ADC_CHANNEL_16;
179+
if ((ADCName)obj->handle.Instance == ADC_1) {
180+
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
181+
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
182+
}
183+
else {
184+
sConfig.Channel = ADC_CHANNEL_16;
185+
}
178186
break;
179187
case 17:
180-
sConfig.Channel = ADC_CHANNEL_17;
188+
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
189+
if ((ADCName)obj->handle.Instance == ADC_1) {
190+
sConfig.Channel = ADC_CHANNEL_VBAT;
191+
}
192+
#if defined(ADC2)
193+
if ((ADCName)obj->handle.Instance == ADC_2) {
194+
sConfig.Channel = ADC_CHANNEL_VOPAMP2;
195+
}
196+
#endif
197+
#if defined(ADC3)
198+
if ((ADCName)obj->handle.Instance == ADC_3) {
199+
sConfig.Channel = ADC_CHANNEL_VOPAMP3;
200+
}
201+
#endif
202+
#if defined(ADC4)
203+
if ((ADCName)obj->handle.Instance == ADC_4) {
204+
sConfig.Channel = ADC_CHANNEL_VOPAMP4;
205+
}
206+
#endif
181207
break;
182208
case 18:
183-
sConfig.Channel = ADC_CHANNEL_18;
209+
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
210+
sConfig.Channel = ADC_CHANNEL_VREFINT;
184211
break;
185212
default:
186213
return 0;

targets/TARGET_STM/TARGET_STM32F3/device/stm32f3xx_hal_adc.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@
4747
/* Include ADC HAL Extended module */
4848
/* (include on top of file since ADC structures are defined in extended file) */
4949
#include "stm32f3xx_hal_adc_ex.h"
50-
50+
51+
/* Include low level driver */
52+
#include "stm32f3xx_ll_adc.h"
53+
5154
/** @addtogroup STM32F3xx_HAL_Driver
5255
* @{
5356
*/

targets/TARGET_STM/TARGET_STM32F3/device/stm32f3xx_hal_adc_ex.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5660,12 +5660,6 @@ HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConf
56605660
/* Set handle of the other ADC sharing the same common register */
56615661
ADC_COMMON_ADC_OTHER(hadc, &tmphadcSharingSameCommonRegister);
56625662

5663-
/* Software is allowed to change common parameters only when all ADCs */
5664-
/* of the common group are disabled. */
5665-
if ((ADC_IS_ENABLE(hadc) == RESET) &&
5666-
( (tmphadcSharingSameCommonRegister.Instance == NULL) ||
5667-
(ADC_IS_ENABLE(&tmphadcSharingSameCommonRegister) == RESET) ) )
5668-
{
56695663
/* If Channel_16 is selected, enable Temp. sensor measurement path */
56705664
/* Note: Temp. sensor internal channels available on ADC1 only */
56715665
if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && (hadc->Instance == ADC1))
@@ -5694,17 +5688,6 @@ HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConf
56945688
{
56955689
SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);
56965690
}
5697-
}
5698-
/* If the requested internal measurement path has already been */
5699-
/* enabled and other ADC of the common group are enabled, internal */
5700-
/* measurement paths cannot be enabled. */
5701-
else
5702-
{
5703-
/* Update ADC state machine to error */
5704-
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
5705-
5706-
tmp_hal_status = HAL_ERROR;
5707-
}
57085691
}
57095692

57105693
}

targets/TARGET_STM/TARGET_STM32F4/analogin_device.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,15 @@ uint16_t adc_read(analogin_t *obj)
161161
break;
162162
case 16:
163163
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
164+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the temperature is 10us
164165
break;
165166
case 17:
166167
sConfig.Channel = ADC_CHANNEL_VREFINT;
167-
/* From experiment, measurement needs max sampling time to be valid */
168-
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
168+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the internal reference voltage is 10us
169169
break;
170170
case 18:
171171
sConfig.Channel = ADC_CHANNEL_VBAT;
172-
/* From experiment, measurement needs max sampling time to be valid */
173-
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
172+
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; // Minimum ADC sampling time when reading the VBAT is 5us
174173
break;
175174
default:
176175
return 0;

targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_hal_adc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
/* Includes ------------------------------------------------------------------*/
4545
#include "stm32f4xx_hal_def.h"
4646

47+
/* Include low level driver */
48+
#include "stm32f4xx_ll_adc.h"
49+
4750
/** @addtogroup STM32F4xx_HAL_Driver
4851
* @{
4952
*/

targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_ll_adc.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,18 @@ extern "C" {
269269
/* ADC registers bits positions */
270270
#define ADC_CR1_RES_BITOFFSET_POS (24U) /* Value equivalent to POSITION_VAL(ADC_CR1_RES) */
271271
#define ADC_TR_HT_BITOFFSET_POS (16U) /* Value equivalent to POSITION_VAL(ADC_TR_HT) */
272+
273+
/* ADC internal channels related definitions */
274+
/* Internal voltage reference VrefInt */
275+
#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). */
276+
#define VREFINT_CAL_VREF ( 3300U) /* Analog voltage reference (Vref+) value with which temperature sensor has been calibrated in production (tolerance: +-10 mV) (unit: mV). */
277+
/* Temperature sensor */
278+
#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). */
279+
#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). */
280+
#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). */
281+
#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). */
282+
#define TEMPSENSOR_CAL_VREFANALOG ( 3300U) /* Analog voltage reference (Vref+) voltage with which temperature sensor has been calibrated in production (+-10 mV) (unit: mV). */
283+
272284
/**
273285
* @}
274286
*/
@@ -1654,6 +1666,64 @@ typedef struct
16541666
/ __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__) \
16551667
)
16561668

1669+
/**
1670+
* @brief Helper macro to calculate the temperature (unit: degree Celsius)
1671+
* from ADC conversion data of internal temperature sensor.
1672+
* @note Computation is using temperature sensor calibration values
1673+
* stored in system memory for each device during production.
1674+
* @note Calculation formula:
1675+
* Temperature = ((TS_ADC_DATA - TS_CAL1)
1676+
* * (TS_CAL2_TEMP - TS_CAL1_TEMP))
1677+
* / (TS_CAL2 - TS_CAL1) + TS_CAL1_TEMP
1678+
* with TS_ADC_DATA = temperature sensor raw data measured by ADC
1679+
* Avg_Slope = (TS_CAL2 - TS_CAL1)
1680+
* / (TS_CAL2_TEMP - TS_CAL1_TEMP)
1681+
* TS_CAL1 = equivalent TS_ADC_DATA at temperature
1682+
* TEMP_DEGC_CAL1 (calibrated in factory)
1683+
* TS_CAL2 = equivalent TS_ADC_DATA at temperature
1684+
* TEMP_DEGC_CAL2 (calibrated in factory)
1685+
* Caution: Calculation relevancy under reserve that calibration
1686+
* parameters are correct (address and data).
1687+
* To calculate temperature using temperature sensor
1688+
* datasheet typical values (generic values less, therefore
1689+
* less accurate than calibrated values),
1690+
* use helper macro @ref __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS().
1691+
* @note As calculation input, the analog reference voltage (Vref+) must be
1692+
* defined as it impacts the ADC LSB equivalent voltage.
1693+
* @note Analog reference voltage (Vref+) must be either known from
1694+
* user board environment or can be calculated using ADC measurement
1695+
* and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE().
1696+
* @note On this STM32 serie, calibration data of temperature sensor
1697+
* corresponds to a resolution of 12 bits,
1698+
* this is the recommended ADC resolution to convert voltage of
1699+
* temperature sensor.
1700+
* Otherwise, this macro performs the processing to scale
1701+
* ADC conversion data to 12 bits.
1702+
* @param __VREFANALOG_VOLTAGE__ Analog reference voltage (unit: mV)
1703+
* @param __TEMPSENSOR_ADC_DATA__ ADC conversion data of internal
1704+
* temperature sensor (unit: digital value).
1705+
* @param __ADC_RESOLUTION__ ADC resolution at which internal temperature
1706+
* sensor voltage has been measured.
1707+
* This parameter can be one of the following values:
1708+
* @arg @ref LL_ADC_RESOLUTION_12B
1709+
* @arg @ref LL_ADC_RESOLUTION_10B
1710+
* @arg @ref LL_ADC_RESOLUTION_8B
1711+
* @arg @ref LL_ADC_RESOLUTION_6B
1712+
* @retval Temperature (unit: degree Celsius)
1713+
*/
1714+
#define __LL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\
1715+
__TEMPSENSOR_ADC_DATA__,\
1716+
__ADC_RESOLUTION__) \
1717+
(((( ((int32_t)((__LL_ADC_CONVERT_DATA_RESOLUTION((__TEMPSENSOR_ADC_DATA__), \
1718+
(__ADC_RESOLUTION__), \
1719+
LL_ADC_RESOLUTION_12B) \
1720+
* (__VREFANALOG_VOLTAGE__)) \
1721+
/ TEMPSENSOR_CAL_VREFANALOG) \
1722+
- (int32_t) *TEMPSENSOR_CAL1_ADDR) \
1723+
) * (int32_t)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP) \
1724+
) / (int32_t)((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) \
1725+
) + TEMPSENSOR_CAL1_TEMP \
1726+
)
16571727

16581728
/**
16591729
* @brief Helper macro to calculate the temperature (unit: degree Celsius)

0 commit comments

Comments
 (0)