cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 on-chip temperature sensor reading stable on 'Y' revision, but unstable on 'V' revision chip

Jack3
Senior II

using the STM32H753VIT6, I like to monitor the on-chip temperature sensor. The environmental temperature can become about 50 degrees Celsius, and the board is housed is a small plastic (DIN-rail) enclosure. This enclosure is fitted in a metal cabinet.

The measurement worked stable on a revision 'Y' of the STM32H7, but now I finally got the recommended revision 'V' of the MCU, where the reading is very unstable, when reading every second. It may vary more than 15 degrees Celsius between two readings.

The board design did not change.

On the other hand, there are differences between the ADC peripheral registers between the 'Y' and 'V' versions. I have read AN5312 Migration from RevY to RevV for STM32H7xx Value line microcontrollers: https://www.st.com/resource/en/application_note/dm00609692.pdf

And I also checked the errata sheet: https://www.st.com/resource/en/errata_sheet/dm00368411.pdf

Is anybody able to get stable reading from the internal temperature sensor?

My ADC init:

/* ADC3 init function */
void MX_ADC3_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* Common config */
  hadc3.Instance = ADC3;
  hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV64;
  hadc3.Init.Resolution = ADC_RESOLUTION_16B;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = ENABLE;
  hadc3.Init.NbrOfConversion = 1;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc3.Init.Overrun = 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 */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  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;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

Initialisation function:

void MCU_TemperatureInit(void)
{
    HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
 
    HAL_ADC_Start_IT(&hadc3);
}
 

The value is read from the interrupt:

ADC_Value = HAL_ADC_GetValue(&hadc3);

The calculation done on the value:

uint16_t MCU_TemperatureCalculate(uint32_t ts_data)
{
  // 0x1FF1E820 Calibration ADC value at 30 °C = 0x2fc0, 12224
  uint16_t ts_cal1 = *(uint16_t*) (TS_CAL1_REG);
  // 0x1FF1E840 Calibration ADC value at 110 °C = 0x3cb4, 15540
  uint16_t ts_cal2 = *(uint16_t*) (TS_CAL2_REG);
 
  return (80 * (ts_data - ts_cal1)) / (ts_cal2 - ts_cal1) + 30;
}
 

I tried different values for ClockPrescaler and SamplingTime as well as different PLL settings for the ADC, but it did not improve.

What can I do to get stable readings, like on the 'Y' version? Any help would be appreciated.

Heavy filtering seems to work, but I wonder if something could be wrong.

11 REPLIES 11

Hi

Using

  • HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);
  • __HAL_ADC_CALC_TEMPERATURE(MB_ANALOGTEMP_REF_VOLT_MV, raw_adc_value, ADC_RESOLUTION_16B);

seems to work.

The Temperature is between 46 and 49°C.

No idea, what was wrong at my calculation.

Thank you

Jakob

Where did MB_ANALOGTEMP_REF_VOLT_MV come from?