Lately, I decided to give the STM32F0 discovery board  a try. The ADC
seemed to be extremely noisy and I decided to investigate the problem.
I'd like to present my results here, just in case someone else
experiences the same problems.
* STM32F0 discovery board
* ADC clock from internal 14MHz oscillator
* Analog input 10 (GPIOC0, configured as analog I/O, of course): I use
1.5 ADC clock cycles sampling time with this input
* Internal voltage reference: I use the advised 239.5 ADC clock cycles
sampling time here.
* FTDI USB<->RS232 converter
* STM32F0 running at 48MHz PLL source, clocked from internal 8MHz RC
* STM32F0 connected to FTDI via USART1, 19200 baud (highest setting
that works reliably with the internal RC oscillator)
I measured the internal voltage reference and an external voltage
applied to GPIOC0. For the voltage reference, I transmitted the raw ADC
values to the PC, for the external voltage I transmitted the calculated
Every value was converted to decimal (for easy debugging) and output to
the serial port. This should result in about 400 readings per second (I
didn't verify this, because that's not very important here).
The external voltage is generated by a 22k potentiometer connected to
VDD and GND. The cable from the potentiometer to the I/O-Pin is about
As a side note: The DC resistance of the potentiometer is far higher
than the suggested value which may have caused an unneglectable loading
of the potentiometer voltage divider and thus cause a voltage deviation
from the unloaded value. I'm aware of this but in this series of
measurements I was not interested in such effects (which may even grow
with the sample rate (higher sample rate -> more S&H cycles per second
-> more input current)). I take the ADC input voltage (which, for
absolute accuracy checks I measured directly at the ADC input) as given
and I am only interested in how to get low noise and a stable rading for
At least 40e3 values were acquired for each dataset.
Potentiometer connected to GPIOC0. In the middle of the cable,
approximately 20cm from the PC0 pin header of the discovery board, I
connected a 100nF ceramic capacitor from PC0 to ground. The purpose is
to lower the dynamic impedance of the potentiometer. This reduces the
noise introduced by the ADC sample and hold considerably. Otherwise the
impedance of the potentiometer would be far too high.
The result was a disaster. You can see a plot of the acquired values in
PC0.pdf, dataset (a). The plot shows a time-series of the first 5e3
datapoints in the left subplot and a histogram of all datapoints in the
right one. Yes, the input voltage was only about 200mV in this case but
the noise wasn't better with higher values. The measured voltage
scattered roughly 100mV in total, a completely unacceptable result.
This time I selected the internal voltage reference as input. This
should rule out any problems caused by long external cables and bad
external setup. The result is plotted in vref.pdf, dataset (a).
At least the individual ADC counts are visible in the time series plot,
but the scatter is horrible, again. The center part of the histogram
looks somewhat "gaussian" but not the tails left and right. Something's
obviously wrong here.
As it turns out, ST didn't respect their own power supply decoupling
requirements. The STM32F0 discovery board doesn't seem to have any
capacitors on the VSSA and VDDA analog supply pins, whereas the
datasheet tells us 1uF || 10nF is required .
I put a piece of PCB onto the top of the MCU with double sided adhesive
tape and soldered the decoupling capacitors onto it (see setup.jpg).
I repeated the second test, now with the decoupling capacitors in place.
The result can be seen in vref.pdf, dataset (b). The result looks much
better, the tails in the histogram have gone, the scatter is smaller.
This was a first step, but the results of the external voltage didn't
improve. I decided to move the 100nF cap very close to the I/O pin and
therefore placed it on top of the MCU, too (see setup.jpg).
Repetition of the first test. Result in PC0.pdf, dataset (b). Almost all
of the scatter is gone. Don't worry about the different average value.
I've touched the potentiometer between the tests. Please notice that the
highest bar of the histogram goes up far higher but I set a limit of 0.3
on the y-axis.
Summary, possible explanations and lessons learned
Apart from the proper supply decoupling, it is extremely important to
drive the ADC input with a very low impedance. This seems obvious -- the
datasheet (, Electrical characteristics, Table of R_AIN,max for f_ADC
= 14MHz) lists a required maximum impedance of 400 Ohms for the fastest
sampling time -- but you have to keep in mind, that the impedance must
be provided directly at the MCU pin. The 20cm wire to the capacitor in
the first test completely messed the results up.
For slowly varying inputs (like a potentiometer) it may be sufficient to
connect a capacitor directly to the analog input like I did. (Please
note that I didn't try out the minimum size of this cap, but the 100nF
seem reasonable as you can see by this eyeball-calculation: The S&H
capacitance is about Cint = 8pF, according to the documentation . The
ADC has 12bits, thus we have 4096 values. If we allow a voltage change
of the external capacitor Cext of one step size during the sampling
process and assume that all current is drawn solely from Cext, we arrive
at the conclusion that Cext > Cint*4096 = approx. 33nF. Add some safety
margin and you arrive at 100nF for a standard value.)
If you want to digitize a fast changing signal, you'll probably need a
very fast buffer close to the ADC input; The fastest sampling time is
only 110ns(!) and the buffer should keep the ADC input voltage stable
during this time.
: RM0091: Reference Manual, STM32F05xxx/06xxx advanced ARM-based
 STM32F051x4 STM32F051x6 STM32F051x8: Data sheet
 UM1525: User Manual, STM32F0DISCOVERY, Discovery kit for STM32 F0