2024-07-29 07:59 AM - last edited on 2024-09-24 05:23 AM by Amel NASRI
Hello, Friends,
I am using ADC(16 bit) to measure the STM32H747 Internal Temperature and VrefInt based on external reference voltage (VDDA 3.3V, Vref+ 2.5V). The VrefInt result is 1.221V, which looks good. However, the temperature result is 150C, which seems not correct.
From the STM32H747xl/G datasheet, there are temperature sensor calibration values TS_CAL1(30C) and TS_CAL2(130C). The formular to get real temperature is (130-30)*(myADCValue-TS_CAL1)/(TS_CAL2-TS_CAL1)+30.
Here are my questions: 1) Is the formular correct? 2)Which reference voltage value is used when TS_CAL2/TS_CAL1 values are read during the calibration? I am using 2.5V external voltage in my design.
Regards,
YH
Solved! Go to Solution.
2024-07-30 11:41 AM
> (100 * ((ts_data*33/25) - ts_cal1)) / (ts_cal2 - ts_cal1) + 30 = 291 C
Should be
(100 * ((ts_data*25/33) - ts_cal1)) / (ts_cal2 - ts_cal1) + 30 = 45 C
45 C seems right.
2024-07-29 08:11 AM - edited 2024-07-29 08:14 AM
This is my function...
Read the parameters stored at the calibration address to get the offsets, and then calculate the slope.
GET_TEMPERATURE is the ADC value.
Don't forget to configure the ADC channel for internal temperature also.
float InternalTemperature(void)
{
float Temp;
s16 Offset;
s16 dT,dx;
s16 NewADCTemp;
dx=T2-T1;
dT=TEMPSENSOR_CAL2_TEMP-TEMPSENSOR_CAL1_TEMP;
Offset=TEMPSENSOR_CAL1_TEMP;
NewADCTemp=GET_TEMPERATURE();//The Raw value
Temp=(dT*(T2-NewADCTemp))/dx+Offset;//DegC - Nearest Integer
return Temp;
}
ADC config:
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 0;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;//ADC_EXTERNALTRIGCONV_T1_CC1;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
//Error_Handler();
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;//was 480
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
// Error_Handler();
}
if(HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* Start Conversation Error */
// Error_Handler();
}
HAL_ADC_PollForConversion(&hadc1, 10);
T1=*((uint16_t*)0x1FFF7A2EU);//@30C
T2=*((uint16_t*)0x1FFF7A2CU);//@110C
2024-07-29 09:16 AM
Hi Rob,
Thank you for the reply. I am pretty sure my ADC set up is OK because it gets correct VrefInt values(1.221V) now. My main concerns are those temperature calibration values from the data sheet. Are they based on some internal reference voltages (2.5/2.048/1.8/1.5) during the calibration measurement? My ADC design is using 2.5V external voltage(VREFBUF_CSR setting is 0x02, HIZ =1, ENVR = 0). I am guessing the ADC reference voltage makes the difference.
2024-07-29 12:07 PM
Hmm, yes you are right I think - if Vref is not 3.3V, then you will most likely need to do some scaling.
When I did it, I'm pretty sure I had Vref tied to 3V3.
RM0433 Page 992 of the manual is a little vague to say the least, but TS_CAL1/2 are measured with Vref at 3V3 as far as I can tell.
Have to admit it is a while since I did it, but I did write the values down by hand to do a sanity check on the maths I didn't have my 12 or 16-bit shifts incorrect, and the register values made sense.
I would start by simply factoring the CAL values e.g.
TS_Cal1_New=TSCal_1*Vref/3V3.
There could of course be an offset to apply as well...
2024-07-29 12:09 PM
It should be stated better, but they're taken with VREF+ = VDDA. The specification on VDDA is 3.3 V +/- 10 mV per the datasheet.
2024-07-30 09:57 AM - edited 2024-07-30 10:03 AM
Hi Rob,
Thank you for the reply. I am using 2.5/3.3 factoring into the calculation temperature
ADC3 read ts_data = 17237
ts_cal1 = 12464 (30 C)
ts_cal2 = 16403 (130 C)
(100 * ((ts_data*33/25) - ts_cal1)) / (ts_cal2 - ts_cal1) + 30 = 291 C
Is this temperature correct? It seems to be too high.
I am using DMA transfer the 4 ranks ADC data. One of the rank is connected to internal Vrefint. It's result is correct because it is close to Vref calibration data from the flash. Hence, I am pretty sure the data reading from ADC channels should be good.
ADC3 read Vrefint = 32025
Vrefint *2500/(0xffff-1) = 1221 mV
Calibration data from flash vr_cal = 24193
vr_cal*3300/(0xffff-1)) = 1218 mV
2024-07-30 11:41 AM
> (100 * ((ts_data*33/25) - ts_cal1)) / (ts_cal2 - ts_cal1) + 30 = 291 C
Should be
(100 * ((ts_data*25/33) - ts_cal1)) / (ts_cal2 - ts_cal1) + 30 = 45 C
45 C seems right.
2024-07-30 11:59 AM
Hi TDK,
Thank you for the reply.