cancel
Showing results for 
Search instead for 
Did you mean: 

Wrong voltage typed at Vrefint STM32C092

morris
Associate III

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
1 ACCEPTED SOLUTION

Accepted Solutions
morris
Associate III

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

View solution in original post

3 REPLIES 3
waclawek.jan
Super User

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

morris
Associate III

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

waclawek.jan
Super User

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