Skip to main content
Visitor
October 22, 2026
Question

STM32H743 Internal Temperature Measurement discrepancy with measured external temperature

  I am noticing a particular issue while measuring the internal temperature sensor using ADC on an STM32H743. Since my Vref tends to vary with temperature, I am internally sampling the Vref to measure the correct reference to the temperature sensing unit.  

In the main codeblock that calculates the temperature from the ADC values, I am using the built-in calibrated values for 30C and 110C. Please see below. 

 

My ADC is setup in the following way. 

static void MX_ADC3_Init(void)
{
  hadc3.Instance = ADC3;
  hadc3.Init.Resolution = ADC_RESOLUTION_16B;
  hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = DISABLE;
  hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;   // 64 MHz / 4 = 16 MHz
  // --- CRITICAL POLLING SEQUENCE CORRECTIONS ---
  hadc3.Init.NbrOfConversion = 2;
  hadc3.Init.DiscontinuousConvMode = ENABLE/*DISABLE*/; // Pauses sequence after each rank
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN/*ADC_OVR_DATA_PRESERVED*/;
  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc3.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */

  // NEW: Rank 1 = internal voltage reference (used to compute actual VDDA)
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  // NEW: Rank 2 = internal temperature sensor
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  // NEW: ADC offset/linearity calibration (was never performed). Must be done after init/config, before conversions.
  if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK)
  {
    Error_Handler();
  }

}

 

In my main loop, I am  using the following codeblock.

mcu_adc_ok = 0;
          vrefint_data = 0;
          temp_adc_value = 0;
          // Read Rank 1
          if (HAL_ADC_Start(&hadc3) == HAL_OK)
          {
            if (HAL_ADC_PollForConversion(&hadc3, 10) == HAL_OK)
            {
              vrefint_data = HAL_ADC_GetValue(&hadc3); // Grabs Rank 1, clears EOC 
              hadc3.Instance->CR |= ADC_CR_ADSTART;    // Read Rank 2
              
              if (HAL_ADC_PollForConversion(&hadc3, 10) == HAL_OK)
              {
                temp_adc_value = HAL_ADC_GetValue(&hadc3); // Grabs Rank 2, clears EOC
                mcu_adc_ok = 1;
              }
            }
            HAL_ADC_Stop(&hadc3);
          }
          if (mcu_adc_ok && (vrefint_data != 0))
          {
            float ts_cal1 = (float)(*TEMPSENSOR_CAL1_ADDR);   // raw @ 30C, VDDA = 3.3V
            float ts_cal2 = (float)(*TEMPSENSOR_CAL2_ADDR);   // raw @ 110C, VDDA = 3.3V
            float vcal    = (float)(*VREFINT_CAL_ADDR);       // raw VREFINT @ 3.3V
            float ts_comp;
            
            MCU_vdda = 3.3f * vcal / (float)vrefint_data;     // measured VDDA in volts
            
            if ((MCU_vdda < 2.7f) || (MCU_vdda > 3.6f)) mcu_adc_ok = 0;   // sanity check
            else
            {
              ts_comp = (float)temp_adc_value * MCU_vdda / 3.3f;   // temp sensor counts normalized to VDDA = 3.3V
              MCU_temp = ((ts_comp - ts_cal1) * (float)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP))
                / (ts_cal2 - ts_cal1) + (float)TEMPSENSOR_CAL1_TEMP;
            }
          }
          else 
            mcu_adc_ok = 0;

 

To test this setup, I have placed the circuit board in an environment chamber at temperatures ranging from -30C to 50C. As a control, I put a thermocouple on the surface of the STM32. 

I am attaching a  plot of  Measured MCU temperature (listed as InnerBall on the X axis) vs Thermocouple (TC) temperature. (At the time of post, this window does not let me paste the image here or attach a file here. )

Thermocouple_temperature  = 1.2*MCU_Temperature -10.8C. 

Question: I can believe that there is an offset between the meaured temperature on the outside of the STM and the internal silicon junction temperature. But why is there a gain (1.2) between the measured internal temperature and the measured outside skin temperature of this STM. 

Thanks in advance. 

Notes: This result is consistent across measuring 5 different units. 

5 replies

TDK
October 22, 2026

Note that the chip generates heat when it works and the internal junction temperature will be higher than ambient. On this chip, typically by 10-20 C. This is expected. It seems you understand this, just saying it for clarity.

But why is there a gain (1.2) between the measured internal temperature and the measured outside skin temperature of this STM. 

At higher temperatures, under the same operating conditions, the (difference between ambient and junction temperature) will be larger as electronics are less efficient at higher temperatures. This effect should show up more as exponential than linear.

It’s also possible the 110 C upper calibration bound you are using is incorrect. I believe this has been fixed in the datasheets and HAL, but you should double check.

 

Hard to know without seeing data.

You didn’t actually show your measured vs expected temperatures anywhere. You can attach an image or paste it with ctrl+v if it’s in your clipboard.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Visitor
October 22, 2026

Thanks TDK.

Perhaps it is a browser issue, but I am unable to attach or paste any figure to this. This is the reason for not putting up the data from the test. Here is the data. 

Chamber Temp

STM Temp

Thermocouple

-30

-7

-20

-10

7

0

10

23

17

30

39

37

50

55

57

I believe I am reading from the correct location. In my code block

float ts_cal1 = (float)(*TEMPSENSOR_CAL1_ADDR);   // raw @ 30C, VDDA = 3.3V
float ts_cal2 = (float)(*TEMPSENSOR_CAL2_ADDR); // raw @ 110C, VDDA = 3.3V

From the _adc.h file:

#define TEMPSENSOR_CAL1_ADDR               ((uint16_t*) (0x1FF1E820UL)) /* Internal temperature sensor, address of parameter TS_CAL1: On STM32H7, 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*) (0x1FF1E840UL)) /* Internal temperature sensor, address of parameter TS_CAL2: On STM32H7, temperature sensor ADC raw data acquired at temperature 110 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */

 

TDK
October 22, 2026

If you have a revision V chip, which is most likely, the upper bound is 130 C. The REV_ID field in the DBGMCU_IDC register can be read to read your chip version.

https://www.st.com/resource/en/datasheet/stm32h743bi.pdf

 

I would show a screenshot, but it appears the forum isn’t allowing pictures to be inserted. This is a new issue. The forum software is awful and actively getting worse it seems, so I am not surprised. No doubt the same issue you are seeing.

 

The temperature and comments about the temperature are correct in the latest version of the HAL library. Your code is from an version at least 2 years old. (Edit: This is incorrect. Some comments still say 110, but shouldn’t.)

https://github.com/STMicroelectronics/stm32h7xx-hal-driver/blob/e3c518ebda3e00c8e52b1625ca44fba65da3b63e/Inc/stm32h7xx_ll_adc.h#L394

"If you feel a post has answered your question, please click ""Accept as Solution""."
TDK
October 22, 2026

For the screenshot issue, it appears the forum has been intentionally crippled in the name of security:

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
Visitor
October 23, 2026

 Much appreciated.

The issue with Revision V and HAL1.11.1 wiht the incorrect _adc.h header explains my problem. 
 

#define TEMPSENSOR_CAL1_ADDR               ((uint16_t*) (0x1FF1E820UL)) /* Internal temperature sensor, address of parameter TS_CAL1: On STM32H7, 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*) (0x1FF1E840UL)) /* Internal temperature sensor, address of parameter TS_CAL2: On STM32H7, temperature sensor ADC raw data acquired at temperature 110 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */

TEMPSENSOR_CAL1_ADDR and TEMPSENSOR_CAL2_ADDR still hold the calibrated values for my RevisionV STM32H743, but I incorrectly calculate the slope using 

(float)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP)

 

For sanity check: (130-30)/(110-30) = 1.25. Which is approximately the “gain” I observed. 

Thanks TDK.