G030 temperature sensor results (very) inaccurate
Hello all,
I am trying to read temperature with the G030. At the moment there is quite a large difference between actual temperature and temperature read by the MCU (true temperature around 23.5 degC while MCU reads 32 degC)
ADC_Init code:
static void ADC_Init(void)
{
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_ADC1);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC1->DR);
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)®_buf);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, BL);
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC1, &ADC_InitStruct);
LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE);
volatile uint32_t wait_loop_index = 0;
/* Poll for ADC channel configuration ready */
while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0)
{
wait_loop_index++;
if (wait_loop_index >= GENERAL_TIMEOUT)
{
Error_Handler();
}
}
/* Clear flag ADC channel configuration ready */
LL_ADC_ClearFlag_CCRDY(ADC1);
LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_ASYNC_DIV8);
LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_GRP_REGULAR_CONTINUED);
LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_256, LL_ADC_OVS_SHIFT_RIGHT_4);
LL_ADC_SetOverSamplingDiscont(ADC1, LL_ADC_OVS_REG_CONT);
LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_HIGH);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_19CYCLES_5);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_2, LL_ADC_SAMPLINGTIME_160CYCLES_5);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);
/* Enable ADC internal voltage regulator */
LL_ADC_EnableInternalRegulator(ADC1);
/* Enable VREFINT and TEMPSENSOR */
SET_BIT(ADC->CCR, LL_ADC_PATH_INTERNAL_VREFINT);
SET_BIT(ADC->CCR, LL_ADC_PATH_INTERNAL_TEMPSENSOR);
/* Delay for ADC internal voltage regulator stabilization. */
/* Compute number of CPU cycles to wait for, from delay in us. */
/* Note: Variable divided by 2 to compensate partially */
/* CPU processing cycles (depends on compilation optimization). */
/* Note: If system core clock frequency is below 200kHz, wait time */
/* is only a few CPU processing cycles. */
wait_loop_index = 0;
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
ADC_SetMode(ADC_RUN_REG_InitStruct, ADIN_CHANNEL, LL_ADC_SAMPLINGTIME_COMMON_1);
}Main clock is 64Mhz, and there is /8 divider on ADC clock, and with 160.5 cycle sampling period, sampling time should be ~20us (which meets sampling time requirement of 5us) unless my math is wrong (however when there is no divider on ADC clock it gives the same result, and sampling time is only ~2.5us)
Temperature sensor reading code:
static void Get_Temp_Vref(void)
{
int32_t result = 0;
LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);
/* Configure ADC for VREFINT sampling*/
ADC_SetMode(ADC_CAL_REG_InitStruct, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_COMMON_1);
LL_ADC_EnableIT_EOS(ADC1);
LL_ADC_ClearFlag_EOS(ADC1);
ADC_Start();
while(!LL_ADC_IsActiveFlag_EOS(ADC1));
LL_ADC_ClearFlag_EOS(ADC1);
ADC_Stop();
result = ADC1->DR;
Vref_Factor = 3.0 *(*VREFINT_CAL_ADDR << 4) / result / 65535; //Vref_Factor * ADC result = actual voltage at ADC input
/* Configure ADC for TEMPSENSOR sampling*/
ADC_SetMode(ADC_CAL_REG_InitStruct, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_COMMON_2);
LL_ADC_EnableIT_EOS(ADC1);
LL_ADC_ClearFlag_EOS(ADC1);
ADC_Start();
while(!LL_ADC_IsActiveFlag_EOS(ADC1));
LL_ADC_ClearFlag_EOS(ADC1);
ADC_Stop();
result = ADC1->DR;
LL_ADC_DisableIT_EOS(ADC1);
Temperature = (Vref_Factor * result - (3.0 * *TEMPSENSOR_CAL1_ADDR / 4096.0)) / (0.0025) + 30;
}I read VREFINT first to convert result to absolute voltage, then use that to calculate temperature.
What did I do wrong? Please help! Thanks in advance!
