cancel
Showing results for 
Search instead for 
Did you mean: 

ADC reading problem

sherif
Associate II
Posted on September 28, 2013 at 21:19

Hi all

This task is absolutely simple and I'm really wondering why i'm having a problem with it. I'm supposed to read the battery level via the ADC on stm32f100c8. What i'm doing is completely and utterly basic, nothing big! Take a look at this:

void ADC_Config(void)
{
/* Enables the High Speed APB (APB2) peripheral clock, ADC1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/**
* Steps to switch the ADC ON
* Initialize ADC1 with the parameters
* Assign the channels
* Enable the interrupts
* Enable ADC DMA transfer
* Enable the ADC
* Calibrate the ADC
* Start conversion
*/
/* Initialize the ADC1 according to the ADC_InitStructure members */
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* Configures ADC1 Channel0 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
/* Enable ADC1 EOC interrupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Reset the ADC1 Calibration registers */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* It is recommended to start calibration for the ADC after each power up */
/* Start the ADC1 Calibration */
ADC_StartCalibration(ADC1);
/* Get the ADC1 calibration status */
while(ADC_GetCalibrationStatus(ADC1));
/* Start by software the ADC1 Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
/* ADC ISR */
void __attribute__ ((interrupt)) __cs3_isr_adc1_2 (void)
{
static uint8 counter = 0;
static uint16 ConvertedValue = 0;
if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
{
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
/* Clear the ADC1 EOC interrupt pending bit */
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
if(ConversionIsComplete == 0)
{
counter++;
ConvertedValue += ADC_GetConversionValue(ADC1);
if(counter == 10) /* Collect 10 values and take the average */
{
BatteryADCValue = ConvertedValue/(uint16)(counter);
ConvertedValue = 0;
counter = 0;
ConversionIsComplete = 1; /* Raise a flag to check on in main */
}
}
}
}
int main(void)
{
/* System Clocks Configurations */
RCC_Config();
/* IOs Configurations */
Port_Config();
/* ISR Configurations */
NVIC_Config();
/* ADCs Configurations */
ADC_Config();
while(1)
{
if(ConversionIsComplete)
{
CheckBatteryLevel();
ConversionIsComplete = 0; /* Reset the Flag */
}
}
}

Forget about any unmentioned functions, the problem is that I receive different value than what I actually read from the pin via the avometer. The conversion value when using a source of 3.2volts is around 28 When applying this value to this equation: Vin = Vdigital*Vref/2^12, Vin = 2.2volts which might have been sensible only if the avometer reads the same, but it doesn't, it reads 1.87volts. Another nonsense arises when I change the sampling rate, like if I used 5 cycles instead of 5, the digital output decreases to around 2 The battery level doesn't have that much of fluctuations to differ from one sampling rate to another! #adc
3 REPLIES 3
raptorhal2
Lead
Posted on September 29, 2013 at 16:06

You missed a clue - the 239.5 sampling time results in the expected converted value.

There is nothing wrong with the code. The problem is that the battery has a limited current drive ability to charge up the ADC multiplexor sample and hold capacitor. The longer sample time is needed to get the capacitor fully charged.

Cheers, Hal

sherif
Associate II
Posted on September 29, 2013 at 17:18

That sounds reasonable but it only resolves the second part of the problem.

raptorhal2
Lead
Posted on September 30, 2013 at 14:06

Check for other possible other problem sources:

The ADC pin not initialized in AN mode.

The ADC pin is also connected to something else (a common problem on Discovery kits).

Incorrect ADC clock speed.

Cheers, Hal