Skip to main content
Associate II
April 13, 2026
Solved

Wrong voltage typed at Vrefint STM32C092

  • April 13, 2026
  • 3 replies
  • 237 views

morris_0-1776092976724.png

Skärmbild 2026-04-13 153204.png

I have followed the datasheets and tried to calculate my reference voltage. I am supplying steady 3V on Vref+ pin but I wanted to confirm this because I have some troubles with the ADC precision.

So I read the internal voltage both on my card and on a nucelo-C092rc. This is my results:

 

My board:

Vref+ = 3.0 * 1659 / 1805 = 2.755

Nucelo board:

Vref+ = 3.0 * 1665 / 1641 = 3.043

However I am quite certain that the nucelo boards are using 3.3 V as reference and my board are using 3 V as reference.

So if I swap the 3.0 V from the datasheet into 3.3 V I get the following:

My board:

Vref+ = 3.3 * 1659 / 1805 = 3.033

Nucelo board:

Vref+ = 3.3 * 1665 / 1641 = 3.348

Which match more my expectations, can someone confirm or deny this typo?

I add my adc init function:

u16 uiDelay = 0;

 ADC_CFGR2.CKMODE = 0x0; // Clock mode set to ADCCLK
 ADC_CCR.PRESC = 0x2; // ADC prescaler set to 48MHz / 4 = 12MHz
 ADC_CFGR1.RES = 0x0; // Set 12 bit resolution

 ADC_SMPR = 0x07; // Sampling time set to 1,5 ADC clock cycles, ADC_ACTIVE_CHANNELS*Sampling time should be less than the ISR period to insure we have new
 // measurements
 ADC_CCR.VREFEN = 1; // Enable VREFINT

 ADC_CFGR1.EXTEN = 0x1; // Trigger ADC rising edge
 ADC_CFGR1.EXTSEL = 0x0; // Trigger conversion on TIM1_TRGO
 ADC_CFGR1.SCANDIR = 0; // 0 = scan from CHSEL0 to max
 ADC_CFGR1.ALIGN = 0; // Right data align AC results

 ADC_CHSELR = ADC_ACTIVE_CHANNELS; // Select channels to be scanned

 ADC_CR.ADVREGEN = 1; // Enable the ADC Voltage regulator
 for (int i = 0; i < ADC_SETUP_TIME; i++); // After ADC_CR.ADVREGEN is set, the mcu have to wait t_ADCVREG_STUP before calibration, see datasheet

 ADC_CR.ADCAL = 1; // Initiate calibration of the ADC
 while (ADC_CR.ADCAL); // Loop until the calibration is complete

 ADC_CR.ADEN = 1; // Enable the ADC

 while (ADC_ISR.ADRDY == 0) // After ADC_CR.ADEN is set it needs the time t_STAB to be ready, see datasheet.
 {
 uiDelay++;
 if (uiDelay > ADC_SETUP_TIME) // If the ADC is not ready after some time, re-enable it.
 {
 uiDelay = 0;
 ADC_CR.ADEN = 1;
 }
 }

 DMA1.DMA_CH1.CPAR = (u32)(&(ADC_DR)); // Set DMA to read from ADC data register
 DMA1.DMA_CH1.CMAR = (u32)(gv_vuiADC_RSLT); // Write destination

 DMA1.DMA_CH1.CNDTR = ADC_Last; // No of bytes to be processed acc to datasheet??? #no of channels according to example

 DMA1.DMA_CH1.CCR.MSIZE = 1; // Memory size is 16 bits
 DMA1.DMA_CH1.CCR.PSIZE = 1; // Peripheral size is 16 bits
 DMA1.DMA_CH1.CCR.MINC = 1; // Enable memory increment mode
 DMA1.DMA_CH1.CCR.CIRC = 1; // Circular adressing
 DMA1.DMA_CH1.CCR.DIR = 0; // Read from peripheral

 DMAMUX_C0CR.DMAREQ_ID = 0x05; // Set DMA request identification, ADC is 5;
 DMAMUX_C0CR.EGE = 0; // Event generation disabled
 DMAMUX_C0CR.SE = 0; // Sync Disabled
 DMAMUX_C0CR.NBREQ = 0x01; // Number of DMA requests

 u16 uiGarbage = ADC_DR; // Read the ADC Data register to clear prior conversion flags

 ADC_CFGR1.DMAEN = 1; // Enable DMA
 ADC_CFGR1.DMACFG = 1; // Circular mode

 DMA1.DMA_CH1.CCR.EN = 1; // Enable DMA

 ADC_CR.ADSTART = 1; // Start a conversion
Best answer by morris

Yes correct, I found it. The ADC self calibration didnt apply

3 replies

waclawek.jan
Super User
April 14, 2026

The Vrefint nominal value is 1.23V, which corresponds to ADC readout of 1679 at Vref+=3.0V, which quite well corresponds to VREFINT_CAL what you've read out from both chips' system memory.

I'd say, the problem is in your program, either in calibration or somewhere in the measurement. You don't use the ST-provided CMSIS-mandated device headers, so even there can be errors.

Try to measure a grounded pin, or a pin at Vref/2.

JW

morrisAuthorBest answer
Associate II
April 16, 2026

Yes correct, I found it. The ADC self calibration didnt apply

waclawek.jan
Super User
April 16, 2026

Thanks for coming back with the solution.

> ADC self calibration didnt apply

Can you please tell us, why? A quick look at the code provided above appears to show that you did perform the self calibration.

JW