2025-01-28 01:22 AM - edited 2025-01-28 01:24 AM
Hello everyone,
it was required that my software periodically measures the internal chip temperature for comparison with the externally measured temperature. As the time distances between measurements are several minutes, the ADC is to be completely turned off in between. I mostly copied the code from the LoRaWAN_End_Node example, but the measured temperature is always too low, around 5-6 °C when it should be around 20-21 °C.The ADC code is generally generated by CubeMX.
MCU is the STM32WLE5CCU.
I've pasted the code here:
void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.NbrOfConversion = 1;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_160CYCLES_5;
hadc.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
uint32_t test_adc_readChannels(uint32_t channel)
{
uint32_t ADCxConvertedValues = 0;
ADC_ChannelConfTypeDef sConfig =
{ 0 };
MX_ADC_Init();
/* Start Calibration */
if (HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK)
{
Error_Handler();
}
/* Configure Regular Channel */
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_ADC_Start(&hadc) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
/** Wait for end of conversion */
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
/** Wait for end of conversion */
HAL_ADC_Stop(&hadc); /* it calls also ADC_Disable() */
ADCxConvertedValues = HAL_ADC_GetValue(&hadc);
HAL_ADC_DeInit(&hadc);
return ADCxConvertedValues;
}
uint16_t test_adc_measureBat(void)
{
uint16_t batteryLevelmV = 0;
uint32_t measuredLevel = 0;
measuredLevel = test_adc_readChannels(ADC_CHANNEL_VREFINT);
if (measuredLevel == 0)
{
batteryLevelmV = 0;
}
else
{
if ((uint32_t)*VREFINT_CAL_ADDR != (uint32_t)0xFFFFU)
{
batteryLevelmV = __LL_ADC_CALC_VREFANALOG_VOLTAGE(measuredLevel, ADC_RESOLUTION_12B);
}
else
{
batteryLevelmV = (VREFINT_CAL_VREF * 1510) / measuredLevel;
}
}
return batteryLevelmV;
}
int16_t test_adc_measureTemp(void)
{
__IO int16_t temperatureDegreeC = 0;
uint32_t measuredLevel = 0;
uint16_t batteryLevelmV = test_adc_measureBat();
measuredLevel = test_adc_readChannels(ADC_CHANNEL_TEMPSENSOR);
/* convert ADC level to temperature */
/* check whether device has temperature sensor calibrated in production */
if (((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) != 0)
{
/* Device with temperature sensor calibrated in production:
use device optimized parameters */
temperatureDegreeC = __LL_ADC_CALC_TEMPERATURE(batteryLevelmV, measuredLevel, LL_ADC_RESOLUTION_12B);
}
else
{
/* Device with temperature sensor not calibrated in production:
use generic parameters */
temperatureDegreeC = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(TEMPSENSOR_TYP_AVGSLOPE, TEMPSENSOR_TYP_CAL1_V,
TEMPSENSOR_CAL1_TEMP, batteryLevelmV, measuredLevel,
LL_ADC_RESOLUTION_12B);
}
/* from int16 to q8.7*/
temperatureDegreeC <<= 8;
return (int16_t)temperatureDegreeC;
}
I've tested with two different baords and had the same problem. The calibrated values for the temperature seem to be valid, and battery measurement seems to give the correct result.
Does anyone have any idea what goes wrong here? I've compared it dozens of times and cannot find the fault.
Solved! Go to Solution.
2025-01-29 12:57 AM
I see. the shift converts to q8.7 fixed point format with 7 fraction binary digits. Thought you did that on purpose due to some internal requirements.