cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103C8 ADC Problem

markbell9
Associate II
Posted on June 12, 2013 at 20:12

Hello --

I'm trying to use the ADC functionality and am having some issues.  I can get different values out of the ADC in response to changing inputs,  but I can not get the EOC (end of conversion) flag to work, nor does the calibration work.

This is my initialization code:

ADC_InitTypeDef ADC_InitStructure;

    /*******************************

    ADC1, Input 0

    ********************************/

    ADC_InitStructure.ADC_Mode                  = ADC_Mode_Independent;

    ADC_InitStructure.ADC_ScanConvMode         = DISABLE;

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

    ADC_InitStructure.ADC_ExternalTrigConv      = ADC_ExternalTrigConv_None;

    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;

    ADC_InitStructure.ADC_NbrOfChannel          = 1;

    /*

     * As per initialization in Board_Init(), I'm running the ADCs at 9 MHz.

     * Total conversion time is  12.5 + 239.5 = 252 cycles.

     * 252 cycles at 9 MHz is 28 uS.

     */

    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1,

                     ADC_SampleTime_239Cycles5);

    ADC_Init ( ADC1, &ADC_InitStructure);

    //Enable ADC 1

    ADC_Cmd (ADC1,ENABLE);

    /*******************************

     ADC2, Input 1

    ********************************/

    ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1,

                  ADC_SampleTime_55Cycles5);

    ADC_Init ( ADC2, &ADC_InitStructure);

    //Enable ADC 2

    ADC_Cmd (ADC2,ENABLE);

    /*******************************

    Calibrate both ADCs

    ********************************/

    //Reset the ADC calibration registers

    ADC_ResetCalibration(ADC1);

#if 0 comment out as this is not yet working.....

    //Wait for reset

    while(ADC_GetResetCalibrationStatus(ADC1));

    ADC_StartCalibration(ADC1);

    //RESET indicates the end of calibration

    while(ADC_GetCalibrationStatus(ADC1));

    //Reset the ADC calibration registers

    ADC_ResetCalibration(ADC2);

    //Wait for reset

    while(ADC_GetResetCalibrationStatus(ADC2));

    ADC_StartCalibration(ADC2);

    //RESET indicates the end of calibration

    while(ADC_GetCalibrationStatus(ADC2));

#endif

This is how I'm calling it the ADC:

      //Start the conversion

      //ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    ADC_Cmd (ADC1,ENABLE);

     //this doesn't work yet....

    //while(RESET == ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))

    val = ADC_GetConversionValue(ADC1);

    sprintf(Debug_String, ''    ADC 1= %d'',val);

I've re-read the manual, checked the registers etc and can't see anything wrong.

Any ideas?

Thank you

Mark

4 REPLIES 4
Posted on June 12, 2013 at 22:06

I've re-read the manual, checked the registers etc and can't see anything wrong. Any ideas?

 

I'd rather look at a stand alone example rather than a selective cut-n-paste. I'm apt to think the problem is elsewhere. The fact the calibration doesn't work suggests one or more of the bus clocks is not enabled.

You'd definitely want to do the ADC_Init() prior to setting up the channels.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
frankfrank956
Associate III
Posted on June 12, 2013 at 23:14

If you have

ADC_InitTypeDef ADC_InitStructure;

inside a function, you will need to initialise that structure completely or the fields that you do not initialise will hold random garbage.

markbell9
Associate II
Posted on June 13, 2013 at 22:37

I changed the ADC_Init() as suggested.  

I am now reading correct voltage leves from both ADCs, but I have to read EACH ADC twice before it will respond with the correct voltage.   I don't know why this is happening.  For example, if the correct ADC value is 0x10 and I change the input, the next ADC read will still return 0x10.  The subsequent one will report the changed value.

The EOC flag seems to be set immediately after I enable the ADC. Is the first read bogus?    I've tried two ways with the same results:

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

    val1 = ADC_GetConversionValue(ADC1);

    ADC_SoftwareStartConvCmd(ADC1, DISABLE);

and

    ADC_Cmd (ADC1,ENABLE);

    while(RESET == ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));

    val1 = ADC_GetConversionValue(ADC1);

I reading the ADC at 5 second intervals so there is ample time for conversion to occur.

Thanks

Mark

markbell9
Associate II
Posted on June 13, 2013 at 23:18

This seems to solve the ''double read'' problem:

    ADC_Cmd (ADC1,ENABLE);

    while(RESET == ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));

    if (SET == ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))

    {

         Delay a while......

    }

    val1 = ADC_GetConversionValue(ADC1);

This tells me the EOC flag is not really set..... ??