I read the messages in here about wrong temperature values including code examples, but still getting wrong values:
I need to measure the internal CPU temperature sensor from the STM32H743XIH6. I activated the ADC3 using STM32CUBEMX (V. 6.9.2) and selected Temperature Channel.
However the calculated temperatures are far too high (140-170):
ADC input clock is set to 37.5 MHz
read T1_30 - address: 0x1FF1E820 - getting value: 0x3064
T1_110 - address: 0x1FF1E840 - getting value: 0x4023
reading GetValue - HAL_ADC_GetValue: 0x4783, 0x4a04, 0x4c68
it is grater than T1_110, how come?!
Mpu internal Temperature: GetValue=0x4783, T1_110=0x4023, T1_30=0x3064
Mpu internal Temperature: 147.47
Mpu internal Temperature: GetValue=0x4a04, T1_110=0x4023, T1_30=0x3064
Mpu internal Temperature: 160.19
Mpu internal Temperature: GetValue=0x4c68, T1_110=0x4023, T1_30=0x3064
Mpu internal Temperature: 172.34
see code below
Any help is very much appreciated!
thanks in advanced
static 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.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.NbrOfDiscConversion = 1;
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;
hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc3.Init.OversamplingMode = ENABLE;
hadc3.Init.Oversampling.Ratio = 256;
hadc3.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
hadc3.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc3.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
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_387CYCLES_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();
}
/* USER CODE BEGIN ADC3_Init 2 */
/* USER CODE END ADC3_Init 2 */
}
uint16_t ReadSingleA2D(void)
{
ADC_ChannelConfTypeDef sConfig;
HAL_StatusTypeDef err;
ADC_HandleTypeDef *hadc;
hadc = &hadc3;
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
// The ADC Boost mode can be controlled through the BOOST bit in the ADC_CR register.
// This bit must be set according to the ADC clock setting. Refer to the ADC_CR register description.
LL_ADC_SetBoostMode(hadc->Instance, LL_ADC_BOOST_MODE_50MHZ);
if((err=HAL_ADCEx_Calibration_Start(hadc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED)) != HAL_OK)
{
ErrorHandler(__FUNCTION__, __LINE__, (char *)"ADC Calibration error=%d", err);
}
if ((err=HAL_ADC_ConfigChannel(hadc, &sConfig)) != HAL_OK)
{
ErrorHandler(__FUNCTION__, __LINE__, (char *)"ADC Config Channel error=%d", err);
}
if ((err=HAL_ADC_Start(hadc)) != HAL_OK)
{
ErrorHandler(__FUNCTION__, __LINE__, (char *)"ADC Start error=%d", err);
}
// wait for the end of conversion
if ((err=HAL_ADC_PollForConversion(hadc, 100)) != HAL_OK)
{
ErrorHandler(__FUNCTION__, __LINE__, (char *)"ADC end of Conversion error=%d", err);
}
return HAL_ADC_GetValue(hadc);
}
void GetMPUTemperature(void)
{
double CelsiusTemperature = 0.0;
uint32_t GetValue = 0;
// read the calibation values
uint32_t T1_30 = (uint32_t) *TEMPSENSOR_CAL1_ADDR;
uint32_t T1_110 = (uint32_t) *TEMPSENSOR_CAL2_ADDR;
// read the temperature
GetValue = ReadSingleA2D(MPU_INTERNAL_TEMPERATURE);
//calculate the temperature in (in °C)
// Analog-to-digital converters (ADC)
// Temperature (in °C) = ((110 °C – 30 °C)/(TS_CAL2 – TS_CAL1))× (TS_DATA – TS_CAL1) + 30 °C
CelsiusTemperature = ( (((double)(110 - 30))/((double)(T1_110 - T1_30))) * ((double)(GetValue - T1_30)) ) + ((double)30);
ErrorHandler(__FUNCTION__, __LINE__,(char *) "Mpu internal Temperature: GetValue=0x%x, T1_110=0x%x, T1_30=0x%x", GetValue, T1_110, T1_30);
ErrorHandler(__FUNCTION__, __LINE__,(char *) "Mpu internal Temperature: %.2f", CelsiusTemperature);
}