cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 on-chip temperature sensor read different values when modifying system clock

Fran9
Associate II

Hi everyone,

As commented in the title, in our system we have two ways of working. At low speed (120MHz) and at high speed (480MHz). When reading the ADC3 (temperature sensor) depending on the mode (low or high speed) I get different values. 

When I work at low speed I can read values around 25º~30º (OK values) but when I read at high speed my values go around 40º~45º.

My config:

I'm using the ADC3 as a temperature sensor with a clock preescaler of SYNC_DIV4 which I understand that I'm taking the sample frequency from AHB.

I have seen that if I use the same SYNC but with another DIV(1 or 2) I obtain wrong values when usign low speed very similar like when working at high speed. But when using ASYNC option values always remain equal, for low speed OK but high speed Wrong.

In clock configuration I have configured the PLL2P to work with the ADC at 5,12Mhz. 

I attach here my configs:

My ADC configuration:

 

void MX_ADC3_Init(void)
{
  /* USER CODE BEGIN ADC3_Init 0 */
  /* USER CODE END ADC3_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC3_Init 1 */
  /* USER CODE END ADC3_Init 1 */

  /** Common config
  */
  hadc3.Instance = ADC3;
  hadc3.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;
  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 = DISABLE;
  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(); //TODO
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_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(); //TODO
  }
  /* USER CODE BEGIN ADC3_Init 2 */
  /* USER CODE END ADC3_Init 2 */
}

 

Reading from ADC:

 

uint32_t readADC(ADC_TypeDef* ADC_instance) //TODO take channels into consideration
{
  uint32_t adc_value = 0;

  if (ADC_instance == ADC3) {
    if(HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK){
      LOG_MESSAGE(ERROR_FILE, "ADC3 calibration failed");
    }
  
    if (HAL_ADC_Start(&hadc3) != HAL_OK){
      LOG_MESSAGE(ERROR_FILE, "ADC3 Start failed");
    }

    // Wait for the conversion to complete
    HAL_ADC_PollForConversion(&hadc3, HAL_ADC3_DELAY);

    // Read the converted value
    adc_value = HAL_ADC_GetValue(&hadc3);

    // Stop the ADC
    HAL_ADC_Stop(&hadc3);
  }
  return adc_value;
}

 

Conversion value.

int32_t readTemperature() {
    int32_t JTemp = 0x0;
    uint32_t raw_value = readADC(ADC_TEMPERATURE_SENSOR);

    JTemp = __HAL_ADC_CALC_TEMPERATURE(3300, raw_value, ADC_RESOLUTION_16B);
    PRINT_DBG_V(PRINTS_VERBOSITY_LOW, "Internal temperature: %ld degrees\r\n", JTemp);
    
    return JTemp;
}

Clock init configuration.

 

void systemClockInitConfig(void)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /* Supply configuration update enable */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /* Configure the main internal regulator output voltage */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

#if defined(SYSTEM_LOW_POWER_120MHZ)
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
#endif

  /** Configure LSE Drive Capability */
  //HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

  /** Macro to configure the PLL clock source */
  __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSI);
  /* Initializes the RCC Oscillators according to the specified parameters in the RCC_OscInitTypeDef structure. */

  /* System clock is initialized using PLL as source */
  systemClockConfigure(SYSTEM_RCC_PLL_DIVN_LP, SYSTEM_RCC_FLASH_LATENCY_LP);

  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_SPI2
                              |RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_SDMMC|RCC_PERIPHCLK_SPI45
                              |RCC_PERIPHCLK_USB|RCC_PERIPHCLK_FMC|RCC_PERIPHCLK_ADC;
  PeriphClkInitStruct.PLL2.PLL2M = 32;
  PeriphClkInitStruct.PLL2.PLL2N = 256;
  PeriphClkInitStruct.PLL2.PLL2P = 100;
  PeriphClkInitStruct.PLL2.PLL2Q = 11;
  PeriphClkInitStruct.PLL2.PLL2R = 8;
  PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;
  PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
  PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
  PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_HCLK;
  PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
  PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
  PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
  PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
  PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C4|RCC_PERIPHCLK_I2C2
                                        |RCC_PERIPHCLK_USART6|RCC_PERIPHCLK_SPI6;
  PeriphClkInitStruct.PLL3.PLL3M = 16;
  PeriphClkInitStruct.PLL3.PLL3N = 64;
  PeriphClkInitStruct.PLL3.PLL3P = 50;
  PeriphClkInitStruct.PLL3.PLL3Q = 6;
  PeriphClkInitStruct.PLL3.PLL3R = 8;
  PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
  PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
  PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
  PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C1235CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_PLL3;
  PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_PLL3;
  PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL3;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

  /** Enable USB Voltage detector */
  HAL_PWREx_EnableUSBVoltageDetector();
}

 

 Clock high speed configuration:

 

void systemClockHighSpeed(void) {
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /* Configure the main internal regulator output voltage */
#if defined(SYSTEM_LOW_POWER_120MHZ)
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
#endif

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); // VOS0 is needed for 480MHz
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /* Change system clock to alternative source */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, SYSTEM_RCC_FLASH_LATENCY_HSI);

  /* Reconfigure PLL1 to achieve desire frequency and select it as system clock source */
  systemClockConfigure(SYSTEM_RCC_PLL_DIVN_HP, SYSTEM_RCC_FLASH_LATENCY_HP);

  /* Reconfigure peripherals and timers as needed */
  configTimPrescaler(TIM2, SYSTEM_RCC_TIM_PRESCALER_HP);
  configTimPrescaler(TIM8, SYSTEM_RCC_TIM_PRESCALER_HP);

  systemUpdateSysTick(); 

  /* WARNING! */
  /* Keep in mind that changing Sysclk can affect other peripherals, with a high risk in communication ones */
  /* At the moment, these could be affected: USART1 (Expansion), USART2 (BLE), USART6 (Scanner), I2C2 (Expansion) */

  return;
}

 

Do you have any idea where the problem may be coming from?

If you need more information I can add it without any problem.

Thank you in advance,

 

PS: I have read this post: https://community.st.com/t5/stm32-mcus-products/stm32h7-on-chip-temperature-sensor-reading-stable-on-y-revision/td-p/300107 but no answer for my problem.

11 REPLIES 11

@Fran9 wrote:

What must be taken into account is that the temperature measured is the internal temperature of the chip and not the superificial one


Given that the sensor is internal to the chip, how could it measure anything other than the internal temperature of the chip?

🤔

I measured the surface temperature.

I have been modifying the chip temperature by external means so I could see how it varied. In this way I was able to make a small characterization of the temperature and understand the results I was seeing.