What you are trying to do is very challenging. Frequency measurement boils down to measuring the time T between corresponding points on the signal waveform (e.g., rising zero crossings) over some number of periods N. The period of the waveform is T/N, and equivalently, the frequency is N/T.
Simple frequency counters just count the number of times that the signal crosses a fixed voltage threshold over a fixed amount of time, and the resulting measurement is relatively crude, with a potential error in N of ±1 whole cycle. This, combined with the accuracy of the counter's internal timebase, determines the accuracy of any particular measurement.
What you are proposing by using an ADC is much more sophisticated, but there are still many issues to overcome before you get to the level of accuracy you're proposing. You'll know N exactly, so the accuracy depends entirely on your ability to measure T. See the following diagram.
To start with, the samples you take are not going to be synchronized to the signal waveform, so it will be necessary to interpolate the position of the actual zero-crossing from the samples on either side of it. The problem is that each sample, represented by a "fuzzy" ellipse above, has a significant amount of uncertainty associated with it.
There are voltage errors, caused by:
- the basic resolution of the ADC
- nonlinearities
- noise
- calibration (scale and offset)
There are also timing errors, caused by:
- sampling frequency error
- jitter
- ADC aperture error
This means that your estimate of the actual waveform (shown as the heavy black lines) could be anywhere in the "error band" represented by the dashed lines. In other words, the interpolated position of each zero crossing will have a timing uncertainty associated with it, shown as ΔT. Note that voltage errors contribute to ΔT because of the finite slope of the signal at each zero-crossing.
The overall period that you're measuring could be as small as T – ΔT or as large as T + ΔT, for a total error of 2ΔT. This means that if you want 12 digits of accuracy, 2ΔT must be less than T × 10-12. Assuming you're taking measurements "quickly" (i.e., T is on the order of 1 second), this means that ΔT must be less than 0.5 ps. 15-digit accuracy would require ΔT less than 0.5 fs. These are not easy numbers to achieve.
That PIC has an internal 1.024V bandgap reference, selected by setting the Channel Select bits to 11111.
So if you set your ADC module's reference to Vdd and then tell it to measure the 1.024V reverence, you can infer back to what your Vdd actually is.
Normally you would work out the voltage on a pin which you've A2D'd with something like:
Vin = (ADCval/ADCrange)*Vref
But in this case its Vin which you know (1.024v) and you want to solve for Vref (your Vdd), so:
Vref = (Vin * ADCrange)/ADCval
or more specifically for your case:
Vdd = (1.024 * 4096)/ADCval
Best Answer
It appears that VREF+ and VREF- are internally tied to VDDA and GND. From the datasheet:
The STM32F030R8 does have an internal voltage reference, but it can only be read by using an ADC input.
Since you do not want to try other options, the answer is: NO, you can't.
I said no because I'm assuming you're a newbie but actually, it can be done. Because VREF+ is connected to VDDA, you can change VDDA to change VREF. I've looked at the Nucleo board's User Manual:
Desolder the SB57 solder bridge first and then connect an external reference to pin 8 of CN5. Make sure that the external reference can supply enough current because it will also have to power the analog section of the MCU.
However, there are some limitations/precautions (please read the datasheet):
1. VDD-VDDA ≤ 0.4V
This means if you want a smaller voltage reference, you may have to lower VDD.
2. VDDA_min = 2.4V
If you want to measure small signal, please consider to use an external ADC or amplifier.