Follow our illustrated blog on Embedded Software Architecture

How to build a hybrid solar/wind energy harvester?

STM32F100: why and how to use the internal reference voltage for ADC?

STM32F100: why and how to use the internal reference voltage for ADC?, 9.1 out of 10 based on 7 ratings
VN:F [1.9.22_1171]
Rating: 9.1/10 (7 votes cast)

One of our main development boards is the  STM32VLDISCOVERY. Its st-link is an in-circuit debugger and programmer, and makes development for prototyping fast and easy. The board has an ‘interesting’ property though: its reference voltage is labeled 3.3V while it is actually… only 3V. Check out the picture for proof!

 stm32f100 3.3 Vref

After reviewing the board schematics we found that a diode ‘D1’ is the cause of this slight voltage drop. The specs of this diode (which is a BAT60JFILM) indicate a forward voltage drop between 0.28V and 0.32V when I=10mA and at a temperature of 25C.

D1 diode stm32f100

Now, why is this so important for us? Because the ADC peripheral uses this reference voltage…well… as a reference input. And thus, when a 12-bit ADC sample needs to be converted into a more meaningful quantity, we need to know this reference voltage. E.g. a 12-bit value of 1234 corresponds to a 904 mV when Vref equals 3000mV (1234 * 3000/4096) and 994 mV when Vref equals 3300mV. That is a significant difference for control applications! Note also that the resolution of the former is a bit higher (0,73 mV per bit instead of 0,81 mV per bit) while its range is a bit lower.

Usually, this reference voltage is a board-specific define in software. But this only works when the Vref is constant…. which is not the case on the STM32 value line discovery board. The reason is the aforementioned diode for which the forward voltage drop is temperature dependent (see spec).

Bridging the diode is one way to solve this issue (Vref then becomes 3.3V again). But we experimented a bit with the internal voltage reference (V_REFINT) of the ADC peripheral. According to the STM32F100 datasheet (see section 5.3.4 embedded reference voltage) V_REFINT is in the range [1.16V-1.26V] with a typical value of 1.2V. Of course, if this value is also temperature-dependent then we have the same problem as with the diode. This is not very clear from the spec though (please share your experience!).

So, how to get V_REFINT? Via channel 17 of the ADC. If you use the STM libraries then you should configure Channel 17 as a regular channel and then enable via ADC_TempSensorVrefintCmd(ENABLE);. Assuming the typical value of 1.2V, you then can calculate the measured voltage via as follows:

x mV = sample_chx * 1200mV / sample_ch17.

So you use the sample from channel 17 (your reference of 1200mV) in order to calculate the voltage of another channel. This way of working is a bit more board independent because one does not need to know the Vref, only the Vrefint which is spec’d by the MCU.

VN:F [1.9.22_1171]
Rating: 9.1/10 (7 votes cast)
About is a joined initiative from Gert Boddaert and Pieter Beyens.
More info: about us, our mission, contact us.


  1. Crystal says

    So how to read voltage on different GPIOs?

  2. Xavier says

    Thanks ! That helped me for a weather station I’m designing for school.

  3. You can also use indirect VRef calibration – connect external reference on ADC input (for ex. TL431 or REF3xxx), periodically measure its voltage, and calculate actual ADC reference from it.

  4. Thanks for your investigation.
    Unfortunately different ADC’s multiplexed inputs give different values for the same voltage, therefore I need particular adjustment for each.

Speak Your Mind