2025-10-12 10:55 AM
I've been trying to read the analog temperature sensor on an STM32H723 MCU. Somehow, my readings were invalid. So, I've started debugging and realized that there are possibly faulty macros defined in stm32h7xx_ll_adc.h (HAL v1.11.5).
As shown below, these macros treat ADC3 (to which the internal temperature and Vref are connected) as a 16-bit ADC instead of a 12-bit ADC. When I use LL_ADC_RESOLUTION_12B instead of LL_ADC_RESOLUTION_16B in those macros, the problem gets solved.
Am I missing something?
/**
* @brief Helper macro to calculate analog reference voltage (Vref+)
* (unit: mVolt) from ADC conversion data of internal voltage
* reference VrefInt.
* @note Computation is using VrefInt calibration value
* stored in system memory for each device during production.
* @note This voltage depends on user board environment: voltage level
* connected to pin Vref+.
* On devices with small package, the pin Vref+ is not present
* and internally bonded to pin Vdda.
* @note On this STM32 series, calibration data of internal voltage reference
* VrefInt corresponds to a resolution of 16 bits,
* this is the recommended ADC resolution to convert voltage of
* internal voltage reference VrefInt.
* Otherwise, this macro performs the processing to scale
* ADC conversion data to 16 bits.
* @PAram __VREFINT_ADC_DATA__ ADC conversion data (resolution 16 bits)
* of internal voltage reference VrefInt (unit: digital value).
* @PAram __ADC_RESOLUTION__ This parameter can be one of the following values:
* @arg @ref LL_ADC_RESOLUTION_16B
* @arg @ref LL_ADC_RESOLUTION_14B
* @arg @ref LL_ADC_RESOLUTION_12B
* @arg @ref LL_ADC_RESOLUTION_10B
* @arg @ref LL_ADC_RESOLUTION_8B
* @retval Analog reference voltage (unit: mV)
*/
#define __LL_ADC_CALC_VREFANALOG_VOLTAGE(__VREFINT_ADC_DATA__,\
__ADC_RESOLUTION__) \
(((uint32_t)(*VREFINT_CAL_ADDR) * VREFINT_CAL_VREF) \
/ __LL_ADC_CONVERT_DATA_RESOLUTION((__VREFINT_ADC_DATA__), \
(__ADC_RESOLUTION__), \
LL_ADC_RESOLUTION_16B) \
)
/**
* @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 series, calibration data of temperature sensor
* corresponds to a resolution of 16 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 16 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_16B
* @arg @ref LL_ADC_RESOLUTION_14B
* @arg @ref LL_ADC_RESOLUTION_12B
* @arg @ref LL_ADC_RESOLUTION_10B
* @arg @ref LL_ADC_RESOLUTION_8B
* @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_16B) \
* (__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 \
)
2025-10-12 1:47 PM
Hello @caglayandokme
You are right, it seems to be an issue on the Driver. @Saket_Om could you please solve this problem.
Best Regards.
II
2025-10-12 1:50 PM
On the first STM32H7 chips, and most of them, ADC3 is a 16-bit ADC and the cal values and LL library macros and comments reflect this.
On the STM32H723, ADC3 is only 12 bits and so are the cal values. However, if you pretend your measurement is 16 bits, and the macro pretends the cal values are 16 bits, the errors cancel out and you'll get the right value.