2025-07-23 10:00 AM
I've used CubeIDE 1.18.1 to create a small project based on a STM32C011F6. The ADC is configired thru Cube to read Vref+, temp sensor and another external voltage.
Cube has therefore created an init function MX_ADC1_Init which is called at during start
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_SEQ_FIXED;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
{
Error_Handler();
}
if (ADC_Enable(&hadc1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END ADC1_Init 2 */
}
Later in the main-loop I read the ADC using DMA with this function
static void adc_read()
{
uint32_t data[3];
data[0] = 0xDEADBEEF; // TRQ_CNT/STL_TH
data[1] = 0xDEADBEEF; // Vsense temperature
data[2] = 0xDEADBEEF; // Vref reference voltage
HAL_ADC_Start_DMA(&hadc1, data, LENOF(data));
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 500) != HAL_OK)
{
Error_Handler();
}
/* Ref-1 16.10 : VREF = VREF_Nominal × VREFINT_CAL / VREFINT_DATA
*/
adc_vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(data[2], LL_ADC_RESOLUTION_12B);
if ((adc_vref < 3200) || (3400 < adc_vref))
{
Error_Handler();
}
/* Ref-2 5.3.16 Temperature sensor characteristics
* Average slope from VSENSE voltage [Avg_Slope] = 2.53mV/C -> 2530uV/C
* Voltage at 30°C (±5 °C) [V30] = 0.76V = 760mV Typ
*
* Sense_Data ADC voltage : sdv = (Vref × Sense_DATA) / 4095
* Temp sensor reference voltage @ RefTemp : trv = (TempVref × Cal1_DATA) / 4095
* Temperature in °C : t = (sdv - trv) / slope + RefTemp
*/
int32_t slope = 2530;
//int32_t calx_v = 760;
int32_t calx_v = (TEMPSENSOR_CAL_VREFANALOG * *TEMPSENSOR_CAL1_ADDR) / __LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B);
int32_t calx_t = TEMPSENSOR_CAL1_TEMP;
adc_temp = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(slope, calx_v,
calx_t, adc_vref, data[1], LL_ADC_RESOLUTION_12B);
/* Get TRQ_CNT/STL_TH in mV
* VCHANNELx = Vref × ADC-DATAx / ADC-Max-Value
*/
trq_cnt = __LL_ADC_CALC_DATA_TO_VOLTAGE(adc_vref, data[0], LL_ADC_RESOLUTION_12B);
}
Vref is tied to nominal +3.3V supply. So when I run this code I get the following ADC values
By using Cube library macros I then get
ADC temp reading seems very off as temp sensor calibration ADC value at 30C (*TEMPSENSOR_CAL1_ADDR) and Vref = 3.0V is 1045.
ADC_CCR::TSEN = 1 after init.
What could cause temperature sensor to return such an incorrect value?
One note about __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS macro:
Parameter __TEMPSENSOR_CALX_TEMP__ is described as
* @PAram __TEMPSENSOR_CALX_TEMP__ Device datasheet data: Temperature at which temperature sensor voltage
(see parameter above) is corresponding (unit: mV)
(unit: mV) must be incorrect. Shouldn't it be (unit: C) ?
Solved! Go to Solution.
2025-07-23 10:26 AM
> ADC_SAMPLETIME_1CYCLE_5
This is not long enough. Increasing sampling time to max. See the datasheet for required minimum sampling duration.
2025-07-23 10:26 AM
> ADC_SAMPLETIME_1CYCLE_5
This is not long enough. Increasing sampling time to max. See the datasheet for required minimum sampling duration.