cancel
Showing results for 
Search instead for 
Did you mean: 

How to have a good precision of ADC on STM32F103C8?

Carter Lee
Associate III
Posted on October 23, 2017 at 05:58

Hi.

Now I'm trying to implement the ADC on the STM32F103C8.

but I came across some problem when I voltage leveling test.

The code is here 

x = getPot()*3.3/4095; //get analog value and convert to volts, 12bit ADC

if(x < 2.2)

{

GPIO_SetBits(GPIOA, GPIO_Pin_4);

GPIO_SetBits(GPIOA, GPIO_Pin_5);

GPIO_ResetBits(GPIOA, GPIO_Pin_6);

GPIO_SetBits(GPIOA, GPIO_Pin_7);

alram = 1;

}

else

{

GPIO_SetBits(GPIOA, GPIO_Pin_4);

GPIO_SetBits(GPIOA, GPIO_Pin_5);

GPIO_SetBits(GPIOA, GPIO_Pin_6);

GPIO_SetBits(GPIOA, GPIO_Pin_7);

alram = 0;

}

the below is what I got the outputs from ports.

0690X00000608eNQAQ.png

As you can see that above image, when I set 2.2v to the ADC then the output is such a mess.

Is there any good way to get a clean operation?

6 REPLIES 6
S.Ma
Principal
Posted on October 23, 2017 at 06:23

x = getPot()*3.3/4095; //get analog value and convert to volts, 12bit ADC

if(x < 2.2)

==> For precise calculation, don't use float with 24 bit mantissa. Try to use integer or something like Q31 format.

Anything analog has noise, this noise level will have at least one LSB amplitude.

Where comes from the noise? Well, mostly from the application itself, the HW, the wires (acting as antenna), etc...

Typically, for a good analog performance, the analog supply should be separated (MCU package dependent). Then, the wires should be at least a twisted pair with ground. Ideally for some STM32, the ADC has differential mode, then the twisted pair becomes like the USB differential pair, which rejects common mode noise (if the signal is disturbed, so is its 'ground' hence it is cancelled out). After this, characterizing the noise will enable proper digital filtering (oversampling is the generic brute force way to reduce noise)...

Posted on October 23, 2017 at 07:01

Thanks, Would you mind giving me some snippet code of that?

Posted on October 23, 2017 at 08:41

==> For precise calculation, don't use float with 24 bit mantissa. Try to use integer or something like Q31 format.

The problem of shown calculation is IMHO more a (massive) waste of performance then a loss of precision.

The F1 parts have no FPU, and you gain nothing compared to integer calculations.

if(x < 2.2)

{

   ...

}

else ...

Apart from that, I suggest a filtering instead of hard decision on just one value ( x ).

matic
Associate III
Posted on October 23, 2017 at 12:09

Another thing to consider when precisely converting ADC value to volts: You should use the actual Vdda value instead of 3.3 V in your equation. See the 'Converting a supply-relative ADC measurement to an absolute voltage value' paragraph on page 375 of the link below (this is the RM for STM32F303, but the principle is the same): 

http://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf

 

For precise conversion you should know what is the Vdda value and for that, you should do another ADC conversion of Vref_int channel.

Best regards.

Posted on October 23, 2017 at 13:27

Digging in the sample code will enable the possibiity to compensate for the MCU VDDA and Temperature (if linear interpolation points are available)