# ADC Calibration - Vdd calculation

In documents and lots of online sources there is a formula as follows,

$$Vdd = 3.3V * \frac{VREFINT_{CAL}}{VREFINT_{DATA}}$$

But I cannot get why CAL value is in the numerator and RAW data is in the denominator. I have this logic in my mind,

In the factory, producers used a preknown/fixed 3.3 V as Vdd and then they get this reference CAL value from ADC. But in reality, my Vdd may be different because of non-idealities. So I read Vref_int channel via my ADC and it gives me RAW. I get the CAL value by reading the device memory address provided by manufacturer. ADC reading and voltage level has a direct relationship. So, I conclude that;

3.3 V ------> CAL(from device memory)

x V ------> RAW(read from Vref_int)

Then, x * CAL = 3.3 * RAW

So, x = 3.3 * RAW/CAL should be my formula to get my current Vdd value so that then I know that a maximum ADC reading (4095 for 12 bits reading for ex.) corresponds to x volts.

However, in the above formula it states that x = 3.3 * CAL/RAW.

My board is STM32F4-DISC.

-------------------- edit ------------------------------------

With all my thanks to the ones who answered, I now understood(I hope) what is going on and want to explain here in detail.

First, what is what :

VREFINT_{CAL} or CAL : The ADC reading of the manufacturer from Vref_int when an exact 3.3V Vdda is used (unitless, 12 bits integer)

VREFINT_{DATA} or RAW : The ADC reading of the user from Vref_int when the Vdda is unknown (unitless, 12 bits integer)

V_{DDA} : Kind of the voltage base for our MCU, when you give a digital high output then it should be exactly equal to Vdda (unit = volts)

Now,

1- In the factory, the manifacturer gets the ADC conversion data from the Vref_int channel and stores it into a memory location as a 12-bit integer. $$\frac{{VREFINT_{voltage}}}{3.3(V_{DDA})}= \frac{{VREFINT_{CAL}(stored\,value\,,CAL)}}{4095} \quad (1)$$ The logic is simple here, 4095 for 3.3V and CAL for Vref_int.

2- When you want to calibrate your voltage level, since you don't know your exact voltage base level, you read the Vref_int yourself and get another ADC conversion value(RAW), let's call it $$VREFINT_{DATA}$$ Then $$\frac{VREFINT_{voltage}}{V_{DDA}(unknown)}= \frac{{VREFINT_{DATA}(measurement\,of\,user\,,RAW)}}{4095}$$

Since $$VREFINT_{voltage}$$ is fixed, replace it with its equivalent from eqn. (1).

Then you can see that the equation yields to $$V_{DDA}(unknown) = \frac{3.3*CAL}{RAW}$$

Finally, you can use this Vdda value as your voltage reference(base) on your calculations.

This edit may include some mistakes, please let me know.

The ADC reading on the VREFINT channel and VDDA have inverse relationship.

An ADC reading is the ratio of the measured voltage to VDDA, scaled up to 4095 (the maximum value that can be expressed on 12 bits). E.g. if you applied VDDA/3 to an ADC input, the result would be 4095/3=1365.

You cant't measure VDDA directly, because if you apply a voltage equal to VDDA to an ADC channel, the conversion result is always 4095.

VREFINT is a fixed voltage generated inside the MCU, around 1.2 volts. When you convert the VREFINT channel of the ADC, you get the ratio of this voltage to VDDA, i.e. 4095*VREFINT/VDDA. Note that VDDA is now in the denominator. If the supply voltage goes down, the conversion result goes up, and vice versa.

Because VREFINT is not an exact voltage source, they measure it in the manufacturing process, using a good stabilized 3.3V supply, and write the conversion result (VREFINTCAL) in the system memory area.

Now if you'd read the VREFINT channel, and got the exact same value that's stored in the system memory, it would mean that VDDA=3.3V, like in the factory calibration process. This is also what the formula in the question gives you when VREFINTCAL = VREFINTDATA.

VREFINTcal is the only known value. The value of VREFINT, when measured with a known good 3.3V Vdd.
If you divide data with cal you know how many bits Vdd is off, assuming VREFINTcal is still valid.

If VREFINTcal is 1000, and data is 1020, this means you've measured VREFINT to be 20 bits higher than it's supposed to be. Indicating a lower Vdd value.
Hence 1000/1020 = 0.98. A 2% difference. Thus 3.3*0.98 = 3.24 V.

You are not measuring the change in VREFINT, but the change of the ADC reference.

• hey, thanks for the answer, i will try to understand it. But in my location, imgur is blocked, if you have time can you please upload image via another source? – muyustan Jul 22 at 10:57
• @muyustan sure, see my edit – Jeroen3 Jul 22 at 11:06
• thanks again, but I cannot get it, what is exactly the vrefintcal value? When I read the vrefint channel on my device with adc, what value do I get? Is it the voltage applied to my board? – muyustan Jul 22 at 11:21
• "If VREFINTcal is 1000, and data is 1020, this means you've measured VREFINT to be 20 bits higher than it's supposed to be", do you really mean bits here? Or do you mean that it is offset by 20? – Harry Svensson Jul 22 at 12:02
• @HarrySvensson Is there another unit for the value that any ADC provides? – Jeroen3 Jul 22 at 13:07

The relationship between ADC input voltage and output value is:

$$IN = \frac{V_{REF} * OUT}{ 4095 }$$

Therefore:

$$VREFINT = \frac{3.3*CAL}{4095} = \frac{V_{DD}*RAW}{4095}$$

Therefore:

$$V_{DD} = \frac{3.3*CAL}{RAW}$$

• by "output code" what do you mean? – muyustan Jul 22 at 12:45
• Sorry, I should say "output value". – Long Pham Jul 22 at 12:47
• hey, now I get the first equation clear. For that equation IN should be a 12-bit ADC reading and OUT is a the measured voltage right? But you wrote "the relationship between adc input voltage and output value". Then I understand from this sentence that volts * volts / unitless = volts which does not sounds right. Is it also a mistake or am I missing something? Thanks anyway – muyustan Jul 22 at 13:32
• @muyustan Oops, my bad, I've corrected the equation. IN is the measured voltage and OUT is the 12-bit ADC reading. – Long Pham Jul 22 at 14:00